<?php

namespace App\Services;

use App\Models\Members\User;
use App\Models\Production\WorkOrderItem;
use Illuminate\Support\Facades\DB;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;

/**
 * 작업실적 서비스
 *
 * 완료된 WorkOrderItem의 options->result 데이터를 기반으로 작업실적 조회/수정
 */
class WorkResultService extends Service
{
    /**
     * 목록 조회 (검색/필터링/페이징)
     *
     * 완료된 WorkOrderItem에서 result 데이터가 있는 항목만 조회
     */
    public function index(array $params)
    {
        $tenantId = $this->tenantId();

        $page = (int) ($params['page'] ?? 1);
        $size = (int) ($params['size'] ?? 20);
        $q = trim((string) ($params['q'] ?? ''));
        $workOrderId = $params['work_order_id'] ?? null;
        $workerId = $params['worker_id'] ?? null;
        $workDateFrom = $params['work_date_from'] ?? null;
        $workDateTo = $params['work_date_to'] ?? null;
        $isInspected = isset($params['is_inspected']) ? filter_var($params['is_inspected'], FILTER_VALIDATE_BOOLEAN) : null;
        $isPackaged = isset($params['is_packaged']) ? filter_var($params['is_packaged'], FILTER_VALIDATE_BOOLEAN) : null;

        $query = WorkOrderItem::query()
            ->where('tenant_id', $tenantId)
            ->where('status', WorkOrderItem::STATUS_COMPLETED)
            ->whereNotNull('options->result')
            ->with([
                'workOrder:id,work_order_no,project_name,process_id,completed_at',
                'workOrder.process:id,process_name,process_code',
            ]);

        // 검색어 (로트번호, 품목명, 작업지시번호)
        if ($q !== '') {
            $query->where(function ($qq) use ($q) {
                $qq->where('options->result->lot_no', 'like', "%{$q}%")
                    ->orWhere('item_name', 'like', "%{$q}%")
                    ->orWhereHas('workOrder', fn ($wo) => $wo->where('work_order_no', 'like', "%{$q}%"));
            });
        }

        // 작업지시 필터
        if ($workOrderId !== null) {
            $query->where('work_order_id', $workOrderId);
        }

        // 작업자 필터
        if ($workerId !== null) {
            $query->where('options->result->worker_id', $workerId);
        }

        // 작업일 범위 (completed_at 기준)
        if ($workDateFrom !== null) {
            $query->where('options->result->completed_at', '>=', $workDateFrom);
        }
        if ($workDateTo !== null) {
            $query->where('options->result->completed_at', '<=', $workDateTo.' 23:59:59');
        }

        // 검사 완료 필터
        if ($isInspected !== null) {
            $query->where('options->result->is_inspected', $isInspected);
        }

        // 포장 완료 필터
        if ($isPackaged !== null) {
            $query->where('options->result->is_packaged', $isPackaged);
        }

        // 최신 완료순 정렬
        $query->orderByDesc('options->result->completed_at')->orderByDesc('id');

        $paginated = $query->paginate($size, ['*'], 'page', $page);

        // worker_id로 작업자 이름 조회하여 추가
        $workerIds = $paginated->getCollection()
            ->map(fn ($item) => $item->options['result']['worker_id'] ?? null)
            ->filter()
            ->unique()
            ->values()
            ->toArray();

        $workers = [];
        if (! empty($workerIds)) {
            $workers = User::whereIn('id', $workerIds)
                ->pluck('name', 'id')
                ->toArray();
        }

        // 각 아이템에 worker_name 추가
        $paginated->getCollection()->transform(function ($item) use ($workers) {
            $workerId = $item->options['result']['worker_id'] ?? null;
            $item->worker_name = $workerId ? ($workers[$workerId] ?? null) : null;

            return $item;
        });

        return $paginated;
    }

    /**
     * 통계 조회
     */
    public function stats(array $params = []): array
    {
        $tenantId = $this->tenantId();

        $workDateFrom = $params['work_date_from'] ?? null;
        $workDateTo = $params['work_date_to'] ?? null;

        $query = WorkOrderItem::where('tenant_id', $tenantId)
            ->where('status', WorkOrderItem::STATUS_COMPLETED)
            ->whereNotNull('options->result');

        // 작업일 범위
        if ($workDateFrom !== null) {
            $query->where('options->result->completed_at', '>=', $workDateFrom);
        }
        if ($workDateTo !== null) {
            $query->where('options->result->completed_at', '<=', $workDateTo.' 23:59:59');
        }

        // JSON에서 집계 (MySQL/MariaDB 기준)
        $items = $query->get();

        $totalProduction = 0;
        $totalGood = 0;
        $totalDefect = 0;

        foreach ($items as $item) {
            $result = $item->options['result'] ?? [];
            $goodQty = (float) ($result['good_qty'] ?? 0);
            $defectQty = (float) ($result['defect_qty'] ?? 0);

            $totalGood += $goodQty;
            $totalDefect += $defectQty;
            $totalProduction += ($goodQty + $defectQty);
        }

        $defectRate = $totalProduction > 0
            ? round(($totalDefect / $totalProduction) * 100, 1)
            : 0;

        return [
            'total_production' => (int) $totalProduction,
            'total_good' => (int) $totalGood,
            'total_defect' => (int) $totalDefect,
            'defect_rate' => $defectRate,
        ];
    }

    /**
     * 단건 조회
     */
    public function show(int $id)
    {
        $tenantId = $this->tenantId();

        $item = WorkOrderItem::where('tenant_id', $tenantId)
            ->where('status', WorkOrderItem::STATUS_COMPLETED)
            ->whereNotNull('options->result')
            ->with([
                'workOrder:id,work_order_no,project_name,process_id,completed_at',
                'workOrder.process:id,process_name,process_code',
            ])
            ->find($id);

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

        // worker_name 추가
        $workerId = $item->options['result']['worker_id'] ?? null;
        if ($workerId) {
            $item->worker_name = User::where('id', $workerId)->value('name');
        } else {
            $item->worker_name = null;
        }

        return $item;
    }

    /**
     * 작업실적 수정 (양품/불량 수량 등)
     */
    public function update(int $id, array $data)
    {
        $tenantId = $this->tenantId();

        $item = WorkOrderItem::where('tenant_id', $tenantId)
            ->where('status', WorkOrderItem::STATUS_COMPLETED)
            ->whereNotNull('options->result')
            ->find($id);

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

        return DB::transaction(function () use ($item, $data) {
            $options = $item->options ?? [];
            $result = $options['result'] ?? [];

            // 수정 가능한 필드만 업데이트
            $allowedFields = ['good_qty', 'defect_qty', 'lot_no', 'is_inspected', 'is_packaged', 'memo'];

            foreach ($allowedFields as $field) {
                if (array_key_exists($field, $data)) {
                    $result[$field] = $data[$field];
                }
            }

            // 불량률 재계산
            $totalQty = ($result['good_qty'] ?? 0) + ($result['defect_qty'] ?? 0);
            $result['defect_rate'] = $totalQty > 0
                ? round(($result['defect_qty'] / $totalQty) * 100, 2)
                : 0;

            $options['result'] = $result;
            $item->options = $options;
            $item->save();

            return $item->fresh([
                'workOrder:id,work_order_no,project_name,process_id',
                'workOrder.process:id,process_name,process_code',
            ]);
        });
    }

    /**
     * 검사 상태 토글
     */
    public function toggleInspection(int $id)
    {
        $tenantId = $this->tenantId();

        $item = WorkOrderItem::where('tenant_id', $tenantId)
            ->where('status', WorkOrderItem::STATUS_COMPLETED)
            ->whereNotNull('options->result')
            ->find($id);

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

        $options = $item->options ?? [];
        $result = $options['result'] ?? [];
        $result['is_inspected'] = ! ($result['is_inspected'] ?? false);
        $options['result'] = $result;
        $item->options = $options;
        $item->save();

        return $item->fresh();
    }

    /**
     * 포장 상태 토글
     */
    public function togglePackaging(int $id)
    {
        $tenantId = $this->tenantId();

        $item = WorkOrderItem::where('tenant_id', $tenantId)
            ->where('status', WorkOrderItem::STATUS_COMPLETED)
            ->whereNotNull('options->result')
            ->find($id);

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

        $options = $item->options ?? [];
        $result = $options['result'] ?? [];
        $result['is_packaged'] = ! ($result['is_packaged'] ?? false);
        $options['result'] = $result;
        $item->options = $options;
        $item->save();

        return $item->fresh();
    }
}
