<?php

namespace App\Services;

use App\Models\Process;
use App\Models\ProcessClassificationRule;
use App\Models\ProcessItem;
use Illuminate\Support\Facades\DB;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;

class ProcessService extends Service
{
    /**
     * 공정 목록 조회 (검색/페이징)
     */
    public function index(array $params)
    {
        $tenantId = $this->tenantId();

        $page = (int) ($params['page'] ?? 1);
        $size = (int) ($params['size'] ?? 20);
        $q = trim((string) ($params['q'] ?? ''));
        $status = $params['status'] ?? null;
        $processType = $params['process_type'] ?? null;

        $query = Process::query()
            ->where('tenant_id', $tenantId)
            ->with(['classificationRules', 'processItems.item:id,code,name', 'steps', 'documentTemplate:id,name,category', 'workLogTemplateRelation:id,name,category']);

        // 검색어
        if ($q !== '') {
            $query->where(function ($qq) use ($q) {
                $qq->where('process_name', 'like', "%{$q}%")
                    ->orWhere('process_code', 'like', "%{$q}%")
                    ->orWhere('description', 'like', "%{$q}%")
                    ->orWhere('department', 'like', "%{$q}%");
            });
        }

        // 상태 필터
        if ($status === 'active') {
            $query->where('is_active', true);
        } elseif ($status === 'inactive') {
            $query->where('is_active', false);
        }

        // 공정구분 필터
        if ($processType) {
            $query->where('process_type', $processType);
        }

        $query->orderBy('process_code');

        return $query->paginate($size, ['*'], 'page', $page);
    }

    /**
     * 공정 상세 조회
     */
    public function show(int $id)
    {
        $tenantId = $this->tenantId();

        $process = Process::where('tenant_id', $tenantId)
            ->with(['classificationRules', 'processItems.item:id,code,name', 'steps', 'documentTemplate:id,name,category', 'workLogTemplateRelation:id,name,category'])
            ->find($id);

        if (! $process) {
            throw new NotFoundHttpException(__('error.not_found'));
        }

        return $process;
    }

    /**
     * 공정 생성
     */
    public function store(array $data)
    {
        $tenantId = $this->tenantId();
        $userId = $this->apiUserId();

        return DB::transaction(function () use ($data, $tenantId, $userId) {
            // 공정코드 자동 생성
            $data['process_code'] = $this->generateProcessCode($tenantId);
            $data['tenant_id'] = $tenantId;
            $data['created_by'] = $userId;
            $data['is_active'] = $data['is_active'] ?? true;

            // work_steps가 문자열이면 배열로 변환
            if (isset($data['work_steps']) && is_string($data['work_steps'])) {
                $data['work_steps'] = array_map('trim', explode(',', $data['work_steps']));
            }

            $rules = $data['classification_rules'] ?? [];
            $itemIds = $data['item_ids'] ?? [];
            unset($data['classification_rules'], $data['item_ids']);

            $process = Process::create($data);

            // 분류 규칙 저장 (패턴 규칙)
            $this->syncClassificationRules($process, $rules);

            // 개별 품목 연결
            $this->syncProcessItems($process, $itemIds);

            return $process->load(['classificationRules', 'processItems.item:id,code,name', 'steps', 'documentTemplate:id,name,category', 'workLogTemplateRelation:id,name,category']);
        });
    }

    /**
     * 공정 수정
     */
    public function update(int $id, array $data)
    {
        $tenantId = $this->tenantId();
        $userId = $this->apiUserId();

        $process = Process::where('tenant_id', $tenantId)->find($id);
        if (! $process) {
            throw new NotFoundHttpException(__('error.not_found'));
        }

        return DB::transaction(function () use ($process, $data, $userId) {
            $data['updated_by'] = $userId;

            // work_steps가 문자열이면 배열로 변환
            if (isset($data['work_steps']) && is_string($data['work_steps'])) {
                $data['work_steps'] = array_map('trim', explode(',', $data['work_steps']));
            }

            $rules = $data['classification_rules'] ?? null;
            $itemIds = $data['item_ids'] ?? null;
            unset($data['classification_rules'], $data['item_ids']);

            $process->update($data);

            // 분류 규칙 동기화 (전달된 경우만)
            if ($rules !== null) {
                $this->syncClassificationRules($process, $rules);
            }

            // 개별 품목 동기화 (전달된 경우만)
            if ($itemIds !== null) {
                $this->syncProcessItems($process, $itemIds);
            }

            return $process->fresh(['classificationRules', 'processItems.item:id,code,name', 'steps', 'documentTemplate:id,name,category', 'workLogTemplateRelation:id,name,category']);
        });
    }

    /**
     * 공정 삭제
     */
    public function destroy(int $id)
    {
        $tenantId = $this->tenantId();
        $userId = $this->apiUserId();

        $process = Process::where('tenant_id', $tenantId)->find($id);
        if (! $process) {
            throw new NotFoundHttpException(__('error.not_found'));
        }

        $process->update(['deleted_by' => $userId]);
        $process->delete();

        return true;
    }

    /**
     * 공정 일괄 삭제
     */
    public function destroyMany(array $ids)
    {
        $tenantId = $this->tenantId();
        $userId = $this->apiUserId();

        $count = Process::where('tenant_id', $tenantId)
            ->whereIn('id', $ids)
            ->update(['deleted_by' => $userId, 'deleted_at' => now()]);

        return $count;
    }

    /**
     * 공정 상태 토글
     */
    public function toggleActive(int $id)
    {
        $tenantId = $this->tenantId();
        $userId = $this->apiUserId();

        $process = Process::where('tenant_id', $tenantId)->find($id);
        if (! $process) {
            throw new NotFoundHttpException(__('error.not_found'));
        }

        $process->update([
            'is_active' => ! $process->is_active,
            'updated_by' => $userId,
        ]);

        return $process->fresh(['classificationRules', 'processItems.item:id,code,name', 'steps', 'documentTemplate:id,name,category', 'workLogTemplateRelation:id,name,category']);
    }

    /**
     * 공정코드 자동 생성 (P-001, P-002, ...)
     */
    private function generateProcessCode(int $tenantId): string
    {
        $lastProcess = Process::where('tenant_id', $tenantId)
            ->withTrashed()
            ->orderByRaw('CAST(SUBSTRING(process_code, 3) AS UNSIGNED) DESC')
            ->first();

        if ($lastProcess && preg_match('/^P-(\d+)$/', $lastProcess->process_code, $matches)) {
            $nextNum = (int) $matches[1] + 1;
        } else {
            $nextNum = 1;
        }

        return sprintf('P-%03d', $nextNum);
    }

    /**
     * 분류 규칙 동기화 (패턴 규칙용)
     */
    private function syncClassificationRules(Process $process, array $rules): void
    {
        // 기존 규칙 삭제
        $process->classificationRules()->delete();

        // 새 규칙 생성 (패턴 규칙만)
        foreach ($rules as $index => $rule) {
            ProcessClassificationRule::create([
                'process_id' => $process->id,
                'registration_type' => 'pattern',
                'rule_type' => $rule['rule_type'],
                'matching_type' => $rule['matching_type'],
                'condition_value' => $rule['condition_value'],
                'priority' => $rule['priority'] ?? $index,
                'description' => $rule['description'] ?? null,
                'is_active' => $rule['is_active'] ?? true,
            ]);
        }
    }

    /**
     * 개별 품목 연결 동기화
     *
     * @param  array  $itemIds  품목 ID 배열
     */
    private function syncProcessItems(Process $process, array $itemIds): void
    {
        // 기존 연결 삭제
        $process->processItems()->delete();

        // 새 연결 생성
        foreach ($itemIds as $index => $itemId) {
            ProcessItem::create([
                'process_id' => $process->id,
                'item_id' => $itemId,
                'priority' => $index,
                'is_active' => true,
            ]);
        }
    }

    /**
     * 드롭다운용 공정 옵션 목록
     */
    public function options()
    {
        $tenantId = $this->tenantId();

        return Process::where('tenant_id', $tenantId)
            ->where('is_active', true)
            ->orderBy('process_code')
            ->select('id', 'process_code', 'process_name', 'process_type', 'department')
            ->get();
    }

    /**
     * 통계
     */
    public function getStats()
    {
        $tenantId = $this->tenantId();

        $total = Process::where('tenant_id', $tenantId)->count();
        $active = Process::where('tenant_id', $tenantId)->where('is_active', true)->count();
        $inactive = Process::where('tenant_id', $tenantId)->where('is_active', false)->count();

        $byType = Process::where('tenant_id', $tenantId)
            ->where('is_active', true)
            ->groupBy('process_type')
            ->selectRaw('process_type, count(*) as count')
            ->pluck('count', 'process_type');

        return [
            'total' => $total,
            'active' => $active,
            'inactive' => $inactive,
            'by_type' => $byType,
        ];
    }
}
