<?php

namespace App\Services;

use App\Enums\InspectionCycle;
use App\Models\Equipment\Equipment;
use App\Models\Equipment\EquipmentInspection;
use App\Models\Equipment\EquipmentInspectionDetail;
use App\Models\Equipment\EquipmentInspectionTemplate;

class EquipmentInspectionService
{
    /**
     * 주기별 점검 데이터 조회
     *
     * @param  string  $cycle  점검주기 (daily/weekly/monthly/bimonthly/quarterly/semiannual)
     * @param  string  $period  기간 (daily: 2026-02, 그 외: 2026)
     */
    public function getInspections(string $cycle, string $period, ?string $productionLine = null, ?int $equipmentId = null): array
    {
        $equipmentQuery = Equipment::where('is_active', true)
            ->where('status', '!=', 'disposed')
            ->with(['manager', 'subManager']);

        if ($productionLine) {
            $equipmentQuery->where('production_line', $productionLine);
        }

        if ($equipmentId) {
            $equipmentQuery->where('id', $equipmentId);
        }

        $equipments = $equipmentQuery->orderBy('sort_order')->orderBy('name')->get();

        $labels = InspectionCycle::columnLabels($cycle, $period);

        $result = [];

        foreach ($equipments as $equipment) {
            $templates = EquipmentInspectionTemplate::where('equipment_id', $equipment->id)
                ->where('inspection_cycle', $cycle)
                ->where('is_active', true)
                ->orderBy('sort_order')
                ->get();

            if ($templates->isEmpty()) {
                continue;
            }

            $inspection = EquipmentInspection::where('equipment_id', $equipment->id)
                ->where('inspection_cycle', $cycle)
                ->where('year_month', $period)
                ->first();

            $details = [];
            if ($inspection) {
                $details = EquipmentInspectionDetail::where('inspection_id', $inspection->id)
                    ->get()
                    ->groupBy(function ($d) {
                        return $d->template_item_id.'_'.$d->check_date->format('Y-m-d');
                    });
            }

            $result[] = [
                'equipment' => $equipment,
                'templates' => $templates,
                'inspection' => $inspection,
                'details' => $details,
                'labels' => $labels,
                'can_inspect' => $equipment->canInspect(),
            ];
        }

        return $result;
    }

    /**
     * 하위호환: 기존 getMonthlyInspections 유지
     */
    public function getMonthlyInspections(string $yearMonth, ?string $productionLine = null, ?int $equipmentId = null): array
    {
        return $this->getInspections(InspectionCycle::DAILY, $yearMonth, $productionLine, $equipmentId);
    }

    /**
     * 셀 토글 (점검 결과 순환)
     */
    public function toggleDetail(int $equipmentId, int $templateItemId, string $checkDate, string $cycle = 'daily'): array
    {
        $equipment = Equipment::findOrFail($equipmentId);
        if (! $equipment->canInspect()) {
            throw new \Exception('점검 권한이 없습니다.');
        }

        $period = InspectionCycle::resolvePeriod($cycle, $checkDate);
        if ($cycle === InspectionCycle::DAILY) {
            $holidayDates = InspectionCycle::getHolidayDates($cycle, $period);
            if (InspectionCycle::isNonWorkingDay($checkDate, $holidayDates)) {
                throw new \Exception('휴일/주말에는 점검을 기록할 수 없습니다.');
            }
        }

        $tenantId = session('selected_tenant_id', 1);

        $inspection = EquipmentInspection::firstOrCreate(
            [
                'tenant_id' => $tenantId,
                'equipment_id' => $equipmentId,
                'inspection_cycle' => $cycle,
                'year_month' => $period,
            ],
            [
                'created_by' => auth()->id(),
            ]
        );

        $detail = EquipmentInspectionDetail::where('inspection_id', $inspection->id)
            ->where('template_item_id', $templateItemId)
            ->where('check_date', $checkDate)
            ->first();

        if ($detail) {
            $nextResult = EquipmentInspectionDetail::getNextResult($detail->result);
            if ($nextResult === null) {
                $detail->delete();

                return ['result' => null, 'symbol' => '', 'color' => 'text-gray-400'];
            }
            $detail->update(['result' => $nextResult]);
        } else {
            $detail = EquipmentInspectionDetail::create([
                'inspection_id' => $inspection->id,
                'template_item_id' => $templateItemId,
                'check_date' => $checkDate,
                'result' => 'good',
            ]);
            $nextResult = 'good';
        }

        return [
            'result' => $nextResult,
            'symbol' => $detail->fresh()->result_symbol,
            'color' => $detail->fresh()->result_color,
        ];
    }

    /**
     * 점검 결과 직접 설정 (모바일용)
     */
    public function setResult(int $equipmentId, int $templateItemId, string $checkDate, string $cycle, ?string $result): array
    {
        $equipment = Equipment::findOrFail($equipmentId);
        if (! $equipment->canInspect()) {
            throw new \Exception('점검 권한이 없습니다.');
        }

        $period = InspectionCycle::resolvePeriod($cycle, $checkDate);
        if ($cycle === InspectionCycle::DAILY) {
            $holidayDates = InspectionCycle::getHolidayDates($cycle, $period);
            if (InspectionCycle::isNonWorkingDay($checkDate, $holidayDates)) {
                throw new \Exception('휴일/주말에는 점검을 기록할 수 없습니다.');
            }
        }

        $tenantId = session('selected_tenant_id', 1);

        $inspection = EquipmentInspection::firstOrCreate(
            [
                'tenant_id' => $tenantId,
                'equipment_id' => $equipmentId,
                'inspection_cycle' => $cycle,
                'year_month' => $period,
            ],
            [
                'created_by' => auth()->id(),
            ]
        );

        $detail = EquipmentInspectionDetail::where('inspection_id', $inspection->id)
            ->where('template_item_id', $templateItemId)
            ->where('check_date', $checkDate)
            ->first();

        if ($result === null) {
            if ($detail) {
                $detail->delete();
            }

            return ['result' => null, 'symbol' => '', 'color' => 'text-gray-400'];
        }

        if ($detail) {
            $detail->update(['result' => $result]);
        } else {
            $detail = EquipmentInspectionDetail::create([
                'inspection_id' => $inspection->id,
                'template_item_id' => $templateItemId,
                'check_date' => $checkDate,
                'result' => $result,
            ]);
        }

        return [
            'result' => $result,
            'symbol' => $detail->fresh()->result_symbol,
            'color' => $detail->fresh()->result_color,
        ];
    }

    public function updateInspectionNotes(int $equipmentId, string $yearMonth, array $data, string $cycle = 'daily'): EquipmentInspection
    {
        $tenantId = session('selected_tenant_id', 1);

        $inspection = EquipmentInspection::firstOrCreate(
            [
                'tenant_id' => $tenantId,
                'equipment_id' => $equipmentId,
                'inspection_cycle' => $cycle,
                'year_month' => $yearMonth,
            ],
            [
                'created_by' => auth()->id(),
            ]
        );

        $inspection->update(array_merge($data, ['updated_by' => auth()->id()]));

        return $inspection->fresh();
    }

    /**
     * 개별 설비 점검 데이터 초기화 (해당 주기/기간)
     */
    public function resetEquipmentInspection(int $equipmentId, string $cycle, string $period): int
    {
        $equipment = Equipment::findOrFail($equipmentId);
        if (! $equipment->canInspect()) {
            throw new \Exception('점검 권한이 없습니다.');
        }

        $tenantId = session('selected_tenant_id', 1);

        $inspection = EquipmentInspection::where('tenant_id', $tenantId)
            ->where('equipment_id', $equipmentId)
            ->where('inspection_cycle', $cycle)
            ->where('year_month', $period)
            ->first();

        if (! $inspection) {
            return 0;
        }

        $deleted = EquipmentInspectionDetail::where('inspection_id', $inspection->id)->delete();
        $inspection->update([
            'overall_judgment' => null,
            'repair_note' => null,
            'issue_note' => null,
            'inspector_id' => null,
            'updated_by' => auth()->id(),
        ]);

        return $deleted;
    }

    /**
     * 전체 점검 데이터 초기화 (해당 주기/기간의 모든 설비)
     */
    public function resetAllInspections(string $cycle, string $period): int
    {
        $tenantId = session('selected_tenant_id', 1);

        $inspections = EquipmentInspection::where('tenant_id', $tenantId)
            ->where('inspection_cycle', $cycle)
            ->where('year_month', $period)
            ->get();

        if ($inspections->isEmpty()) {
            return 0;
        }

        $totalDeleted = 0;
        foreach ($inspections as $inspection) {
            $totalDeleted += EquipmentInspectionDetail::where('inspection_id', $inspection->id)->delete();
            $inspection->update([
                'overall_judgment' => null,
                'repair_note' => null,
                'issue_note' => null,
                'inspector_id' => null,
                'updated_by' => auth()->id(),
            ]);
        }

        return $totalDeleted;
    }

    public function getMonthlyStats(string $yearMonth): array
    {
        $totalEquipments = Equipment::where('is_active', true)
            ->where('status', '!=', 'disposed')
            ->count();

        $inspected = EquipmentInspection::where('year_month', $yearMonth)->count();

        $issueCount = EquipmentInspectionDetail::whereHas('inspection', function ($q) use ($yearMonth) {
            $q->where('year_month', $yearMonth);
        })->where('result', 'bad')->count();

        return [
            'total' => $totalEquipments,
            'inspected' => $inspected,
            'issue_count' => $issueCount,
        ];
    }

    public function saveTemplate(int $equipmentId, array $data): EquipmentInspectionTemplate
    {
        $tenantId = session('selected_tenant_id', 1);

        return EquipmentInspectionTemplate::create(array_merge($data, [
            'tenant_id' => $tenantId,
            'equipment_id' => $equipmentId,
        ]));
    }

    public function updateTemplate(int $id, array $data): EquipmentInspectionTemplate
    {
        $template = EquipmentInspectionTemplate::findOrFail($id);
        $template->update($data);

        return $template->fresh();
    }

    public function deleteTemplate(int $id): bool
    {
        return EquipmentInspectionTemplate::findOrFail($id)->delete();
    }

    /**
     * 점검항목을 다른 주기로 복사
     */
    public function copyTemplatesToCycles(int $equipmentId, string $sourceCycle, array $targetCycles): array
    {
        $tenantId = session('selected_tenant_id', 1);

        $sourceTemplates = EquipmentInspectionTemplate::where('equipment_id', $equipmentId)
            ->where('inspection_cycle', $sourceCycle)
            ->where('is_active', true)
            ->orderBy('sort_order')
            ->get();

        if ($sourceTemplates->isEmpty()) {
            throw new \Exception('복사할 점검항목이 없습니다.');
        }

        $copiedCount = 0;
        $skippedCount = 0;

        foreach ($targetCycles as $targetCycle) {
            foreach ($sourceTemplates as $template) {
                $exists = EquipmentInspectionTemplate::where('equipment_id', $equipmentId)
                    ->where('inspection_cycle', $targetCycle)
                    ->where('item_no', $template->item_no)
                    ->exists();

                if ($exists) {
                    $skippedCount++;

                    continue;
                }

                EquipmentInspectionTemplate::create([
                    'tenant_id' => $tenantId,
                    'equipment_id' => $equipmentId,
                    'inspection_cycle' => $targetCycle,
                    'item_no' => $template->item_no,
                    'check_point' => $template->check_point,
                    'check_item' => $template->check_item,
                    'check_timing' => $template->check_timing,
                    'check_frequency' => $template->check_frequency,
                    'check_method' => $template->check_method,
                    'sort_order' => $template->sort_order,
                    'is_active' => true,
                ]);
                $copiedCount++;
            }
        }

        return [
            'copied' => $copiedCount,
            'skipped' => $skippedCount,
            'source_count' => $sourceTemplates->count(),
            'target_cycles' => $targetCycles,
        ];
    }

    /**
     * 설비에 등록된 점검주기 목록 반환 (항목이 있는 주기만)
     */
    public function getActiveCycles(int $equipmentId): array
    {
        return EquipmentInspectionTemplate::where('equipment_id', $equipmentId)
            ->where('is_active', true)
            ->distinct()
            ->pluck('inspection_cycle')
            ->toArray();
    }
}
