<?php

namespace App\Modules\Production\Controllers;

use App\Http\Controllers\Controller;

use App\Modules\Production\Models\ProductionOrder;
use App\Modules\Production\Models\ProductionOrderItem;
use App\Modules\Inventory\Contracts\InventoryServiceInterface;
use App\Modules\Core\Contracts\CoreServiceInterface;
use App\Modules\Procurement\Contracts\ProcurementServiceInterface;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Inertia\Inertia;
use Inertia\Response;


class ProductionOrderController extends Controller
{
    protected $inventoryService;
    protected $coreService;
    protected $procurementService;

    public function __construct(
        InventoryServiceInterface $inventoryService, 
        CoreServiceInterface $coreService,
        ProcurementServiceInterface $procurementService
    )
    {
        $this->inventoryService = $inventoryService;
        $this->coreService = $coreService;
        $this->procurementService = $procurementService;
    }

    /**
     * 生產工單列表
     */
    public function index(Request $request): Response
    {
        // 不再使用 with()，避免跨模組 Eager Loading
        $query = ProductionOrder::query();

        // 搜尋 (此處 orWhereHas 暫時保留，因 Laravel query builder 仍可作用於資料表層級，
        // 但實務上若模組完全隔離，應考慮搜尋引擎或 ID 預選)
        if ($request->filled('search')) {
            $search = $request->search;
            $query->where(function ($q) use ($search) {
                $q->where('code', 'like', "%{$search}%")
                  ->orWhere('output_batch_number', 'like', "%{$search}%");
                // 若要搜尋產品名稱，現在需先從 Inventory 查出 IDs
                $productIds = $this->inventoryService->getProductsByName($search)->pluck('id');
                $q->orWhereIn('product_id', $productIds);
            });
        }

        // 狀態篩選
        if ($request->filled('status') && $request->status !== 'all') {
            $query->where('status', $request->status);
        }

        // 排除軟刪除
        $query->orderBy($request->input('sort_field', 'created_at'), $request->input('sort_direction', 'desc'));

        // 分頁
        $perPage = $request->input('per_page', 10);
        $productionOrders = $query->paginate($perPage)->withQueryString();

        // --- 手動資料水和 (Manual Hydration) ---
        $productIds = $productionOrders->pluck('product_id')->unique()->filter()->toArray();
        $warehouseIds = $productionOrders->pluck('warehouse_id')->unique()->filter()->toArray();
        $userIds = $productionOrders->pluck('user_id')->unique()->filter()->toArray();

        $products = $this->inventoryService->getProductsByIds($productIds)->keyBy('id');
        $warehouses = $this->inventoryService->getAllWarehouses()->whereIn('id', $warehouseIds)->keyBy('id');
        $users = $this->coreService->getUsersByIds($userIds)->keyBy('id');

        $productionOrders->getCollection()->transform(function ($order) use ($products, $warehouses, $users) {
            $order->product = $products->get($order->product_id);
            $order->warehouse = $warehouses->get($order->warehouse_id);
            $order->user = $users->get($order->user_id);
            return $order;
        });

        return Inertia::render('Production/Index', [
            'productionOrders' => $productionOrders,
            'filters' => $request->only(['search', 'status', 'per_page', 'sort_field', 'sort_direction']),
        ]);
    }

    /**
     * 新增生產單表單
     */
    public function create(): Response
    {
        return Inertia::render('Production/Create', [
            'products' => $this->inventoryService->getAllProducts(),
            'warehouses' => $this->inventoryService->getAllWarehouses(),
            'units' => $this->inventoryService->getUnits(),
        ]);
    }

    /**
     * 儲存生產單（含自動扣料與成品入庫）
     */
    public function store(Request $request)
    {
        $status = $request->input('status', 'draft');

        $rules = [
            'product_id' => 'required',
            'status' => 'nullable|in:draft,completed',
            'warehouse_id' => $status === 'completed' ? 'required' : 'nullable',
            'output_quantity' => $status === 'completed' ? 'required|numeric|min:0.01' : 'nullable|numeric',
            'items' => 'nullable|array',
            'items.*.inventory_id' => $status === 'completed' ? 'required' : 'nullable',
            'items.*.quantity_used' => $status === 'completed' ? 'required|numeric|min:0.0001' : 'nullable|numeric',
        ];

        $validated = $request->validate($rules);

        DB::transaction(function () use ($validated, $request, $status) {
            // 1. 建立生產工單
            $productionOrder = ProductionOrder::create([
                'code' => ProductionOrder::generateCode(),
                'product_id' => $validated['product_id'],
                'warehouse_id' => $validated['warehouse_id'] ?? null,
                'output_quantity' => $validated['output_quantity'] ?? 0,
                'output_batch_number' => $request->output_batch_number, // 建立時改為選填
                'output_box_count' => $request->output_box_count,
                'production_date' => $request->production_date,
                'expiry_date' => $request->expiry_date,
                'user_id' => auth()->id(),
                'status' => ProductionOrder::STATUS_DRAFT, // 一律存為草稿
                'remark' => $request->remark,
            ]);

            activity()
                ->performedOn($productionOrder)
                ->causedBy(auth()->user())
                ->log('created');

            // 2. 處理明細
            if (!empty($request->items)) {
                foreach ($request->items as $item) {
                    ProductionOrderItem::create([
                        'production_order_id' => $productionOrder->id,
                        'inventory_id' => $item['inventory_id'],
                        'quantity_used' => $item['quantity_used'] ?? 0,
                        'unit_id' => $item['unit_id'] ?? null,
                    ]);
                }
            }
        });

        return redirect()->route('production-orders.index')
            ->with('success', '生產單草稿已建立');
    }

    /**
     * 檢視生產單詳情
     */
    public function show(ProductionOrder $productionOrder): Response
    {
        // 手動水和主表資料
        $productionOrder->product = $this->inventoryService->getProduct($productionOrder->product_id);
        if ($productionOrder->product) {
            $productionOrder->product->base_unit = $this->inventoryService->getUnits()->where('id', $productionOrder->product->base_unit_id)->first();
        }
        $productionOrder->warehouse = $productionOrder->warehouse_id 
            ? $this->inventoryService->getWarehouse($productionOrder->warehouse_id)
            : null;
        $productionOrder->user = $this->coreService->getUser($productionOrder->user_id);

        // 手動水和明細資料
        $items = $productionOrder->items;
        $inventoryIds = $items->pluck('inventory_id')->unique()->filter()->toArray();
        
        // 修正: 移除跨模組關聯 sourcePurchaseOrder.vendor
        $inventories = $this->inventoryService->getInventoriesByIds(
            $inventoryIds, 
            ['product.baseUnit', 'warehouse'] 
        )->keyBy('id');
        
        // 手動載入 Purchase Orders
        $poIds = $inventories->pluck('source_purchase_order_id')->unique()->filter()->toArray();
        $purchaseOrders = collect();
        if (!empty($poIds)) {
            $purchaseOrders = $this->procurementService->getPurchaseOrdersByIds($poIds, ['vendor'])->keyBy('id');
        }

        $units = $this->inventoryService->getUnits()->keyBy('id');

        foreach ($items as $item) {
            $item->inventory = $inventories->get($item->inventory_id);
            if ($item->inventory) {
                // 手動掛載 PO
                $poId = $item->inventory->source_purchase_order_id;
                $item->inventory->sourcePurchaseOrder = $purchaseOrders->get($poId);
            }
            $item->unit = $units->get($item->unit_id);
        }

        return Inertia::render('Production/Show', [
            'productionOrder' => $productionOrder,
            'warehouses' => $this->inventoryService->getAllWarehouses(),
        ]);
    }

    /**
     * 取得倉庫內可用庫存
     */
    public function getWarehouseInventories($warehouseId)
    {
        $inventories = $this->inventoryService->getInventoriesByWarehouse($warehouseId);
        
        $data = $inventories->map(function ($inv) {
            return [
                'id' => $inv->id,
                'product_id' => $inv->product_id,
                'product_name' => $inv->product->name ?? '未知商品',
                'product_code' => $inv->product->code ?? '',
                'batch_number' => $inv->batch_number,
                'box_number' => $inv->box_number,
                'quantity' => $inv->quantity,
                'arrival_date' => $inv->arrival_date ? $inv->arrival_date->format('Y-m-d') : null,
                'expiry_date' => $inv->expiry_date ? $inv->expiry_date->format('Y-m-d') : null,
                'unit_name' => $inv->product->baseUnit->name ?? '',
                'base_unit_id' => $inv->product->base_unit_id ?? null,
                'large_unit_id' => $inv->product->large_unit_id ?? null,
                'conversion_rate' => $inv->product->conversion_rate ?? 1,
            ];
        });

        return response()->json($data);
    }

    /**
     * 取得商品在各倉庫的庫存分佈
     */
    public function getProductWarehouses($productId)
    {
        $inventories = \App\Modules\Inventory\Models\Inventory::with(['warehouse', 'product.baseUnit'])
            ->where('product_id', $productId)
            ->where('quantity', '>', 0)
            ->get();
            
        $data = $inventories->map(function ($inv) {
            return [
                'id' => $inv->id, // Inventory ID
                'warehouse_id' => $inv->warehouse_id,
                'warehouse_name' => $inv->warehouse->name ?? '未知倉庫',
                'batch_number' => $inv->batch_number,
                'quantity' => $inv->quantity,
                'expiry_date' => $inv->expiry_date ? $inv->expiry_date->format('Y-m-d') : null,
                'unit_name' => $inv->product->baseUnit->name ?? '',
                'base_unit_id' => $inv->product->base_unit_id ?? null,
                'conversion_rate' => $inv->product->conversion_rate ?? 1,
            ];
        });

        return response()->json($data);
    }

    /**
     * 編輯生產單
     */
    public function edit(ProductionOrder $productionOrder): Response
    {
        if ($productionOrder->status !== 'draft') {
            return redirect()->route('production-orders.show', $productionOrder->id)
                ->with('error', '只有草稿狀態的生產單可以編輯');
        }

        // 基本水和
        $productionOrder->product = $this->inventoryService->getProduct($productionOrder->product_id);
        $productionOrder->warehouse = $productionOrder->warehouse_id 
            ? $this->inventoryService->getWarehouse($productionOrder->warehouse_id)
            : null;
        
        // 手動水和明細資料
        $items = $productionOrder->items;
        $inventoryIds = $items->pluck('inventory_id')->unique()->filter()->toArray();
        $inventories = $this->inventoryService->getInventoriesByIds(
            $inventoryIds, 
            ['product.baseUnit']
        )->keyBy('id');
        
        $units = $this->inventoryService->getUnits()->keyBy('id');

        foreach ($items as $item) {
            $item->inventory = $inventories->get($item->inventory_id);
            $item->unit = $units->get($item->unit_id);
        }

        return Inertia::render('Production/Edit', [
            'productionOrder' => $productionOrder,
            'products' => $this->inventoryService->getAllProducts(),
            'warehouses' => $this->inventoryService->getAllWarehouses(),
            'units' => $this->inventoryService->getUnits(),
        ]);
    }

    /**
     * 更新生產單
     */
    public function update(Request $request, ProductionOrder $productionOrder)
    {
        if ($productionOrder->status !== 'draft') {
             return redirect()->route('production-orders.show', $productionOrder->id)
                ->with('error', '只有草稿可以修改');
        }

        $status = $request->input('status', 'draft');

        // 基礎驗證規則
        $rules = [
            'product_id' => 'required',
            'remark' => 'nullable|string',
            'warehouse_id' => 'nullable',
            'output_quantity' => 'nullable|numeric',
            'items' => 'nullable|array',
            'items.*.inventory_id' => 'required',
            'items.*.quantity_used' => 'required|numeric',
        ];
        
        $validated = $request->validate($rules);

        DB::transaction(function () use ($validated, $request, $productionOrder) {
            $productionOrder->update([
                'product_id' => $validated['product_id'],
                'warehouse_id' => $validated['warehouse_id'] ?? $productionOrder->warehouse_id,
                'output_quantity' => $validated['output_quantity'] ?? 0,
                'output_batch_number' => $request->output_batch_number ?? $productionOrder->output_batch_number,
                'output_box_count' => $request->output_box_count,
                'production_date' => $request->production_date ?? $productionOrder->production_date,
                'expiry_date' => $request->expiry_date ?? $productionOrder->expiry_date,
                'remark' => $request->remark,
            ]);

            activity()
                ->performedOn($productionOrder)
                ->causedBy(auth()->user())
                ->log('updated');

            // 重新建立明細
            $productionOrder->items()->delete();

            if (!empty($request->items)) {
                foreach ($request->items as $item) {
                    ProductionOrderItem::create([
                        'production_order_id' => $productionOrder->id,
                        'inventory_id' => $item['inventory_id'],
                        'quantity_used' => $item['quantity_used'] ?? 0,
                        'unit_id' => $item['unit_id'] ?? null,
                    ]);
                }
            }
        });

        return redirect()->route('production-orders.index')
            ->with('success', '生產單已更新');
    }

    /**
     * 更新生產工單狀態
     */
    public function updateStatus(Request $request, ProductionOrder $productionOrder)
    {
        $newStatus = $request->input('status');
        
        if (!$productionOrder->canTransitionTo($newStatus)) {
            return response()->json(['error' => '不合法的狀態轉移或權限不足'], 403);
        }

        DB::transaction(function () use ($newStatus, $productionOrder, $request) {
            $oldStatus = $productionOrder->status;

            // 1. 執行特定狀態的業務邏輯
            if ($oldStatus === ProductionOrder::STATUS_APPROVED && $newStatus === ProductionOrder::STATUS_IN_PROGRESS) {
                // 開始製作 -> 扣除原料庫存
                $items = $productionOrder->items;
                foreach ($items as $item) {
                    $this->inventoryService->decreaseInventoryQuantity(
                        $item->inventory_id, 
                        $item->quantity_used, 
                        "生產單 #{$productionOrder->code} 開始製作 (扣料)",
                        ProductionOrder::class,
                        $productionOrder->id
                    );
                }
            } 
            elseif ($oldStatus === ProductionOrder::STATUS_IN_PROGRESS && $newStatus === ProductionOrder::STATUS_COMPLETED) {
                // 完成製作 -> 成品入庫
                $warehouseId = $request->input('warehouse_id'); // 由前端 Modal 傳來
                $batchNumber = $request->input('output_batch_number'); // 由前端 Modal 傳來
                $expiryDate = $request->input('expiry_date'); // 由前端 Modal 傳來
                
                if (!$warehouseId) {
                    throw new \Exception('必須選擇入庫倉庫');
                }
                if (!$batchNumber) {
                    throw new \Exception('必須提供成品批號');
                }

                // 更新單據資訊：批號、效期與自動記錄生產日期
                $productionOrder->output_batch_number = $batchNumber;
                $productionOrder->expiry_date = $expiryDate;
                $productionOrder->production_date = now()->toDateString();
                $productionOrder->warehouse_id = $warehouseId;

                $this->inventoryService->createInventoryRecord([
                    'warehouse_id' => $warehouseId,
                    'product_id' => $productionOrder->product_id,
                    'quantity' => $productionOrder->output_quantity,
                    'batch_number' => $batchNumber,
                    'box_number' => $productionOrder->output_box_count,
                    'arrival_date' => now()->toDateString(),
                    'expiry_date' => $expiryDate,
                    'reason' => "生產單 #{$productionOrder->code} 製作完成 (入庫)",
                    'reference_type' => ProductionOrder::class,
                    'reference_id' => $productionOrder->id,
                ]);
            }

            // 2. 更新狀態
            $productionOrder->status = $newStatus;
            $productionOrder->save();

            // 3. 紀錄 Activity Log
            activity()
                ->performedOn($productionOrder)
                ->causedBy(auth()->user())
                ->withProperties([
                    'old_status' => $oldStatus,
                    'new_status' => $newStatus
                ])
                ->log("status_updated_to_{$newStatus}");
        });

        return back()->with('success', '狀態已更新');
    }

    /**
     * 從儲存體中移除指定資源。
     */
    public function destroy(ProductionOrder $productionOrder)
    {
        // 僅允許刪除草稿或已作廢的單據
        if (!in_array($productionOrder->status, [ProductionOrder::STATUS_DRAFT, ProductionOrder::STATUS_CANCELLED])) {
            return redirect()->back()->with('error', '僅有草稿或已作廢的生產單可以刪除');
        }

        DB::transaction(function () use ($productionOrder) {
            $productionOrder->items()->delete();
            $productionOrder->delete();
            
            activity()
                ->performedOn($productionOrder)
                ->causedBy(auth()->user())
                ->log('deleted');
        });

        return redirect()->route('production-orders.index')->with('success', '生產單已刪除');
    }
}
