<?php

namespace App\Http\Controllers;

use App\Models\Documents\Document;
use App\Models\Documents\DocumentData;
use App\Models\DocumentTemplate;
use App\Models\Items\Item;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\DB;
use Illuminate\View\View;

class DocumentController extends Controller
{
    /**
     * 문서 목록 페이지
     */
    public function index(Request $request): View|Response
    {
        if ($request->header('HX-Request')) {
            return response('', 200)->header('HX-Redirect', route('documents.index'));
        }

        $tenantId = session('selected_tenant_id');

        // 템플릿 목록 (필터용)
        $templates = $tenantId
            ? DocumentTemplate::where(function ($q) use ($tenantId) {
                $q->whereNull('tenant_id')->orWhere('tenant_id', $tenantId);
            })->where('is_active', true)->orderBy('name')->get()
            : collect();

        // 양식분류 목록 (필터용)
        $categories = $tenantId
            ? DocumentTemplate::where(function ($q) use ($tenantId) {
                $q->whereNull('tenant_id')->orWhere('tenant_id', $tenantId);
            })->where('is_active', true)
                ->whereNotNull('category')
                ->distinct()
                ->pluck('category')
                ->sort()
                ->values()
            : collect();

        return view('documents.index', [
            'templates' => $templates,
            'categories' => $categories,
            'statuses' => Document::STATUS_LABELS,
        ]);
    }

    /**
     * 문서 생성 페이지
     */
    public function create(Request $request): View|Response
    {
        if ($request->header('HX-Request')) {
            return response('', 200)->header('HX-Redirect', route('documents.create', $request->query()));
        }

        $tenantId = session('selected_tenant_id');
        $templateId = $request->query('template_id');

        // 템플릿 목록
        $templates = $tenantId
            ? DocumentTemplate::where(function ($q) use ($tenantId) {
                $q->whereNull('tenant_id')->orWhere('tenant_id', $tenantId);
            })->where('is_active', true)->orderBy('name')->get()
            : collect();

        // 선택된 템플릿
        $template = $templateId
            ? DocumentTemplate::with(['approvalLines', 'basicFields', 'sections.items', 'columns', 'sectionFields', 'links.linkValues'])->find($templateId)
            : null;

        return view('documents.edit', [
            'document' => null,
            'template' => $template,
            'templates' => $templates,
            'isCreate' => true,
            'linkedItemSpecs' => $template ? $this->getLinkedItemSpecs($template) : [],
        ]);
    }

    /**
     * 문서 수정 페이지
     */
    public function edit(int $id): View|Response
    {
        if (request()->header('HX-Request')) {
            return response('', 200)->header('HX-Redirect', route('documents.edit', $id));
        }

        $tenantId = session('selected_tenant_id');

        $document = Document::with([
            'template.approvalLines',
            'template.basicFields',
            'template.sections.items',
            'template.columns',
            'template.sectionFields',
            'template.links.linkValues',
            'approvals.user',
            'data',
            'attachments.file',
            'creator',
        ])->where('tenant_id', $tenantId)->findOrFail($id);

        // 템플릿 목록 (변경용)
        $templates = $tenantId
            ? DocumentTemplate::where(function ($q) use ($tenantId) {
                $q->whereNull('tenant_id')->orWhere('tenant_id', $tenantId);
            })->where('is_active', true)->orderBy('name')->get()
            : collect();

        // 기본정보 bf_ 자동 backfill (show 안 거치고 바로 edit 진입 대비)
        $this->resolveAndBackfillBasicFields($document);

        return view('documents.edit', [
            'document' => $document,
            'template' => $document->template,
            'templates' => $templates,
            'isCreate' => false,
            'linkedItemSpecs' => $this->getLinkedItemSpecs($document->template),
        ]);
    }

    /**
     * 문서 인쇄용 화면 (성적서 양식)
     */
    public function print(int $id): View
    {
        $tenantId = session('selected_tenant_id');

        $document = Document::with([
            'template.approvalLines',
            'template.basicFields',
            'template.sections.items',
            'template.columns',
            'template.sectionFields',
            'template.links.linkValues',
            'approvals.user',
            'data',
            'creator',
        ])->where('tenant_id', $tenantId)->findOrFail($id);

        // 연결된 작업지시서의 work_order_items 로드
        $workOrderItems = collect();
        if ($document->linkable_type === 'work_order' && $document->linkable_id) {
            $workOrderItems = DB::table('work_order_items')
                ->where('work_order_id', $document->linkable_id)
                ->orderBy('sort_order')
                ->get()
                ->map(function ($item) {
                    $item->options = json_decode($item->options, true) ?? [];

                    return $item;
                });
        }

        // 기본정보 bf_ 자동 backfill
        $this->resolveAndBackfillBasicFields($document);

        return view('documents.print', [
            'document' => $document,
            'workOrderItems' => $workOrderItems,
        ]);
    }

    /**
     * 문서 상세 페이지 (읽기 전용)
     */
    public function show(int $id): View
    {
        $tenantId = session('selected_tenant_id');

        $document = Document::with([
            'template.approvalLines',
            'template.basicFields',
            'template.sections.items',
            'template.columns',
            'template.sectionFields',
            'template.links.linkValues',
            'approvals.user',
            'data',
            'attachments.file',
            'creator',
            'updater',
        ])->where('tenant_id', $tenantId)->findOrFail($id);

        // 연결된 작업지시서의 work_order_items 로드
        $workOrderItems = collect();
        $workOrder = null;
        $salesOrder = null;
        $materialInputLots = collect();
        if ($document->linkable_type === 'work_order' && $document->linkable_id) {
            $workOrderItems = DB::table('work_order_items')
                ->where('work_order_id', $document->linkable_id)
                ->orderBy('sort_order')
                ->get()
                ->map(function ($item) {
                    $item->options = json_decode($item->options, true) ?? [];

                    return $item;
                });

            // 작업일지용: 작업지시 + 수주 + 자재투입LOT 로드
            $workOrder = DB::table('work_orders')
                ->where('id', $document->linkable_id)
                ->first();

            if ($workOrder?->sales_order_id) {
                $salesOrder = DB::table('orders')
                    ->where('id', $workOrder->sales_order_id)
                    ->first();
            }

            // 자재 투입 LOT (stock_transactions 기반, 취소 트랜잭션 상쇄 포함)
            $transactions = DB::table('stock_transactions')
                ->where('tenant_id', $tenantId)
                ->whereIn('reference_type', ['work_order_input', 'work_order_input_cancel'])
                ->where('reference_id', $document->linkable_id)
                ->orderBy('created_at')
                ->get(['lot_no', 'item_code', 'item_name', 'qty', 'reference_type', 'created_at']);

            $lotMap = [];
            foreach ($transactions as $tx) {
                $lotNo = $tx->lot_no;
                if (! isset($lotMap[$lotNo])) {
                    $lotMap[$lotNo] = (object) [
                        'lot_no' => $lotNo,
                        'item_code' => $tx->item_code,
                        'item_name' => $tx->item_name,
                        'total_qty' => 0,
                        'input_count' => 0,
                        'first_input_at' => $tx->created_at,
                    ];
                }
                // OUT(투입)은 음수, IN(취소)은 양수 → 합산하면 순수 투입량
                $lotMap[$lotNo]->total_qty += (float) $tx->qty;
                if ($tx->reference_type === 'work_order_input') {
                    $lotMap[$lotNo]->input_count++;
                }
            }
            // 순수 투입량이 0 이하인 LOT 제외, qty를 절대값으로 변환
            $materialInputLots = collect(array_values($lotMap))
                ->filter(fn ($lot) => $lot->total_qty < 0)
                ->map(function ($lot) {
                    $lot->total_qty = abs($lot->total_qty);

                    return $lot;
                })
                ->values();

            // 개소별 투입자재 LOT (work_order_material_inputs 기반, work_order_item_id → lot_no)
            $itemLotMap = DB::table('work_order_material_inputs as mi')
                ->join('stock_lots as sl', 'sl.id', '=', 'mi.stock_lot_id')
                ->where('mi.work_order_id', $document->linkable_id)
                ->select('mi.work_order_item_id', 'sl.lot_no', 'mi.qty')
                ->orderBy('mi.work_order_item_id')
                ->get()
                ->groupBy('work_order_item_id')
                ->map(fn ($rows) => $rows->pluck('lot_no')->unique()->join(', '));
        }

        // 기본정보 bf_ 자동 backfill
        $this->resolveAndBackfillBasicFields($document);

        return view('documents.show', [
            'document' => $document,
            'workOrderItems' => $workOrderItems,
            'workOrder' => $workOrder,
            'salesOrder' => $salesOrder,
            'materialInputLots' => $materialInputLots,
            'itemLotMap' => $itemLotMap ?? collect(),
        ]);
    }

    /**
     * 기본정보(bf_) 레코드가 없으면 원본 데이터에서 resolve → document_data에 저장
     * 검사 문서: field_key 기반 매핑
     * 작업일지: label 기반 매핑 (DB에서 직접 JOIN)
     */
    private function resolveAndBackfillBasicFields(Document $document): void
    {
        $basicFields = $document->template?->basicFields;
        if (! $basicFields || $basicFields->isEmpty()) {
            return;
        }

        // bf_ 레코드가 하나라도 있으면 이미 저장된 것 → skip
        $existingBfCount = $document->data
            ->filter(fn ($d) => str_starts_with($d->field_key, 'bf_'))
            ->count();
        if ($existingBfCount > 0) {
            return;
        }

        // 원본 데이터 로드: work_order + order
        if ($document->linkable_type !== 'work_order' || ! $document->linkable_id) {
            return;
        }

        $workOrder = DB::table('work_orders')->find($document->linkable_id);
        if (! $workOrder) {
            return;
        }

        $workOrderItems = DB::table('work_order_items')
            ->where('work_order_id', $workOrder->id)
            ->orderBy('sort_order')
            ->get()
            ->map(function ($item) {
                $item->options = json_decode($item->options, true) ?? [];

                return $item;
            });

        $order = $workOrder->sales_order_id
            ? DB::table('orders')->find($workOrder->sales_order_id)
            : null;

        // 작업일지 vs 검사 문서 판별: 섹션이 없으면 작업일지
        $isWorkLog = ! $document->template->sections || $document->template->sections->isEmpty();

        if ($isWorkLog) {
            $resolveMap = $this->buildWorkLogResolveMap($workOrder, $order);
        } else {
            $resolveMap = $this->buildInspectionResolveMap($workOrder, $workOrderItems, $order);
        }

        // document_data에 bf_ 레코드 저장
        $records = [];
        foreach ($basicFields as $field) {
            if ($isWorkLog) {
                // 작업일지: label 기반 매핑
                $value = $resolveMap[$field->label] ?? $field->default_value ?? '';
            } else {
                // 검사 문서: field_key 기반 매핑
                $value = $resolveMap[$field->field_key] ?? $field->default_value ?? '';
            }
            if ($value === '') {
                continue;
            }
            $records[] = [
                'document_id' => $document->id,
                'section_id' => null,
                'column_id' => null,
                'row_index' => 0,
                'field_key' => 'bf_'.$field->id,
                'field_value' => (string) $value,
                'created_at' => now(),
                'updated_at' => now(),
            ];
        }

        if (! empty($records)) {
            DocumentData::insert($records);
            // 메모리의 data relation도 갱신
            $document->load('data');
        }
    }

    /**
     * 작업일지용 기본필드 resolve 맵 (label → 값)
     * API WorkOrderService::buildWorkLogAutoValues 와 동일 매핑
     */
    private function buildWorkLogResolveMap(object $workOrder, ?object $salesOrder): array
    {
        $receivedAt = $salesOrder?->received_at ?? $salesOrder?->created_at ?? null;
        $orderDate = $receivedAt ? substr((string) $receivedAt, 0, 10) : '';
        $deliveryDate = $salesOrder?->delivery_date ?? null;
        $deliveryStr = $deliveryDate ? substr((string) $deliveryDate, 0, 10) : '';
        $orderNo = $salesOrder?->order_no ?? '';

        return [
            '발주처' => $salesOrder?->client_name ?? '',
            '현장명' => $salesOrder?->site_name ?? $workOrder->project_name ?? '',
            '작업일자' => now()->format('Y-m-d'),
            'LOT NO' => $orderNo,
            '납기일' => $deliveryStr,
            '작업지시번호' => $workOrder->work_order_no ?? '',
            '수주일' => $orderDate,
            '수주처' => $salesOrder?->client_name ?? '',
            '담당자' => '',
            '연락처' => '',
            '제품 LOT NO' => $orderNo,
            '생산담당자' => '',
            '출고예정일' => $deliveryStr,
        ];
    }

    /**
     * 검사 문서용 기본필드 resolve 맵 (field_key → 값)
     */
    private function buildInspectionResolveMap(object $workOrder, $workOrderItems, ?object $order): array
    {
        $firstItem = $workOrderItems->first();
        $inspectionData = $firstItem?->options['inspection_data'] ?? [];
        $inspectedBy = $inspectionData['inspected_by'] ?? null;
        $inspectedAt = $inspectionData['inspected_at'] ?? null;
        $inspectorName = $inspectedBy
            ? DB::table('users')->where('id', $inspectedBy)->value('name')
            : null;

        return [
            'product_name' => $firstItem?->item_name ?? '',
            'specification' => $firstItem?->specification ?? '',
            'lot_no' => $order?->order_no ?? '',
            'lot_size' => $workOrderItems->count().' 개소',
            'client' => $order?->client_name ?? '',
            'site_name' => $workOrder->project_name ?? '',
            'inspection_date' => $inspectedAt ? substr($inspectedAt, 0, 10) : now()->format('Y-m-d'),
            'inspector' => $inspectorName ?? '',
        ];
    }

    /**
     * 템플릿에 연결된 품목들의 규격 정보 (thickness, width, length) 조회
     */
    private function getLinkedItemSpecs(DocumentTemplate $template): array
    {
        $specs = [];

        if (! $template->relationLoaded('links')) {
            $template->load('links.linkValues');
        }

        foreach ($template->links as $link) {
            if ($link->source_table !== 'items') {
                continue;
            }

            foreach ($link->linkValues as $lv) {
                $item = Item::find($lv->linkable_id);
                if (! $item) {
                    continue;
                }

                $attrs = $item->attributes ?? [];
                if (isset($attrs['thickness']) || isset($attrs['width']) || isset($attrs['length'])) {
                    $specs[] = [
                        'id' => $item->id,
                        'name' => $item->name,
                        'thickness' => $attrs['thickness'] ?? null,
                        'width' => $attrs['width'] ?? null,
                        'length' => $attrs['length'] ?? null,
                    ];
                }
            }
        }

        return $specs;
    }
}
