<?php

namespace App\Modules\Inventory\Controllers;

use App\Http\Controllers\Controller;
use App\Modules\Inventory\Models\InventoryCountDoc;
use App\Modules\Inventory\Models\Warehouse;
use App\Modules\Inventory\Services\CountService;
use Illuminate\Http\Request;
use Inertia\Inertia;

class CountDocController extends Controller
{
    protected $countService;

    public function __construct(CountService $countService)
    {
        $this->countService = $countService;
    }

    public function index(Request $request)
    {
        $query = InventoryCountDoc::query()
            ->with(['createdBy', 'completedBy', 'warehouse']);

        if ($request->filled('warehouse_id')) {
            $query->where('warehouse_id', $request->warehouse_id);
        }

        if ($request->filled('search')) {
            $search = $request->search;
            $query->where(function ($q) use ($search) {
                $q->where('doc_no', 'like', "%{$search}%")
                  ->orWhere('remarks', 'like', "%{$search}%");
            });
        }

        $perPage = $request->input('per_page', 10);
        if (!in_array($perPage, [10, 20, 50, 100])) {
            $perPage = 10;
        }

        $countQuery = function ($query) {
            $query->whereNotNull('counted_qty');
        };

        $docs = $query->withCount(['items', 'items as counted_items_count' => $countQuery])
            ->orderByDesc('created_at')
            ->paginate($perPage)
            ->withQueryString()
            ->through(function ($doc) {
                return [
                    'id' => (string) $doc->id,
                    'doc_no' => $doc->doc_no,
                    'status' => $doc->status,
                    'warehouse_name' => $doc->warehouse->name,
                    'snapshot_date' => $doc->snapshot_date ? $doc->snapshot_date->format('Y-m-d H:i') : '-',
                    'completed_at' => $doc->completed_at ? $doc->completed_at->format('Y-m-d H:i') : '-',
                    'created_by' => $doc->createdBy?->name,
                    'remarks' => $doc->remarks,
                    'total_items' => $doc->items_count,
                    'counted_items' => $doc->counted_items_count,
                ];
            });

        return Inertia::render('Inventory/Count/Index', [
            'docs' => $docs,
            'warehouses' => Warehouse::all()->map(fn($w) => ['id' => (string)$w->id, 'name' => $w->name]),
            'filters' => $request->only(['warehouse_id', 'search', 'per_page']),
        ]);
    }

    public function store(Request $request)
    {
        $validated = $request->validate([
            'warehouse_id' => 'required|exists:warehouses,id',
            'remarks' => 'nullable|string|max:255',
        ]);

        $doc = $this->countService->createDoc(
            $validated['warehouse_id'],
            $validated['remarks'] ?? null,
            auth()->id()
        );

        // 自動執行快照
        $this->countService->snapshot($doc, false);

        return redirect()->route('inventory.count.show', [$doc->id])
            ->with('success', '已建立盤點單並完成庫存快照');
    }

    public function show(InventoryCountDoc $doc)
    {
        $doc->load(['items.product.baseUnit', 'createdBy', 'completedBy', 'warehouse']);

        // 預先抓取相關的 Inventory 資訊 (主要為了取得效期)
        $inventoryMap = \App\Modules\Inventory\Models\Inventory::withTrashed()
            ->where('warehouse_id', $doc->warehouse_id)
            ->whereIn('product_id', $doc->items->pluck('product_id'))
            ->whereIn('batch_number', $doc->items->pluck('batch_number'))
            ->get()
            ->mapWithKeys(function ($inv) {
                return [$inv->product_id . '-' . $inv->batch_number => $inv];
            });

        $docData = [
            'id' => (string) $doc->id,
            'doc_no' => $doc->doc_no,
            'warehouse_id' => (string) $doc->warehouse_id,
            'warehouse_name' => $doc->warehouse->name,
            'status' => $doc->status,
            'remarks' => $doc->remarks,
            'snapshot_date' => $doc->snapshot_date ? $doc->snapshot_date->format('Y-m-d H:i') : null,
            'created_by' => $doc->createdBy?->name,
            'items' => $doc->items->map(function ($item) use ($inventoryMap) {
                $key = $item->product_id . '-' . $item->batch_number;
                $inv = $inventoryMap->get($key);
                
                return [
                    'id' => (string) $item->id,
                    'product_name' => $item->product->name,
                    'product_code' => $item->product->code,
                    'batch_number' => $item->batch_number,
                    'expiry_date' => $inv && $inv->expiry_date ? $inv->expiry_date->format('Y-m-d') : null, // 新增效期
                    'unit' => $item->product->baseUnit?->name,
                    'system_qty' => (float) $item->system_qty,
                    'counted_qty' => is_null($item->counted_qty) ? '' : (float) $item->counted_qty,
                    'diff_qty' => (float) $item->diff_qty,
                    'notes' => $item->notes,
                ];
            }),
        ];

        return Inertia::render('Inventory/Count/Show', [
            'doc' => $docData,
        ]);
    }

    public function print(InventoryCountDoc $doc)
    {
        $doc->load(['items.product.baseUnit', 'createdBy', 'completedBy', 'warehouse']);

        $docData = [
            'id' => (string) $doc->id,
            'doc_no' => $doc->doc_no,
            'warehouse_name' => $doc->warehouse->name,
            'snapshot_date' => $doc->snapshot_date ? $doc->snapshot_date->format('Y-m-d') : date('Y-m-d'), // Use date only
            'created_at' => $doc->created_at->format('Y-m-d'),
            'print_date' => date('Y-m-d'),
            'created_by' => $doc->createdBy?->name,
            'items' => $doc->items->map(function ($item) {
                return [
                    'id' => (string) $item->id,
                    'product_name' => $item->product->name,
                    'product_code' => $item->product->code,
                    'specification' => $item->product->specification,
                    'unit' => $item->product->baseUnit?->name,
                    'quantity' => (float) ($item->counted_qty ?? $item->system_qty), // Default to system qty if counted is null, or just counted? User wants "Count Sheet" -> maybe blank if not counted?
                    // Actually, if it's "Completed", we show counted. If it's "Pending", we usually show blank or system.
                    // The 'Show' page logic suggests we show counted_qty.
                    'counted_qty' => $item->counted_qty,
                    'notes' => $item->notes,
                ];
            }),
        ];

        return Inertia::render('Inventory/Count/Print', [
            'doc' => $docData,
        ]);
    }

    public function update(Request $request, InventoryCountDoc $doc)
    {
        if ($doc->status === 'completed') {
            return redirect()->back()->with('error', '此盤點單已完成，無法修改');
        }

        $validated = $request->validate([
            'items' => 'array',
            'items.*.id' => 'required|exists:inventory_count_items,id',
            'items.*.counted_qty' => 'nullable|numeric|min:0',
            'items.*.notes' => 'nullable|string',
        ]);

        if (isset($validated['items'])) {
            $this->countService->updateCount($doc, $validated['items']);
        }

        // 重新讀取以獲取最新狀態
        $doc->refresh();

        if ($doc->status === 'completed') {
            return redirect()->route('inventory.count.index')
                ->with('success', '盤點完成，單據已自動存檔並完成。');
        }

        return redirect()->back()->with('success', '盤點資料已暫存');
    }

    public function reopen(InventoryCountDoc $doc)
    {
        // 權限檢查 (通常僅允許有權限者執行，例如 inventory.adjust)
        // 注意：前端已經用 <Can> 保護按鈕，後端這裡最好也加上檢查
        if (!auth()->user()->can('inventory.adjust')) {
            abort(403);
        }

        if (!in_array($doc->status, ['completed', 'no_adjust'])) {
            return redirect()->back()->with('error', '僅能針對已完成或無需盤調的盤點單重新開啟盤點');
        }
        
        // 執行取消核准邏輯
        $doc->update([
            'status' => 'counting',    // 回復為盤點中
            'completed_at' => null,    // 清除完成時間
            'completed_by' => null,    // 清除完成者
        ]);

        return redirect()->back()->with('success', '已重新開啟盤點，單據回復為盤點中狀態');
    }

    public function destroy(InventoryCountDoc $doc)
    {
        if ($doc->status === 'completed') {
            return redirect()->back()->with('error', '已完成的盤點單無法刪除');
        }

        // Activity Log handled by Model Trait

        $doc->items()->delete();
        $doc->delete();

        return redirect()->route('inventory.count.index')
            ->with('success', '盤點單已刪除');
    }
}
