<?php

namespace App\Modules\Inventory\Controllers;

use App\Http\Controllers\Controller;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Inertia\Inertia;
use App\Modules\Inventory\Models\Warehouse;
use App\Modules\Inventory\Models\Product;
use App\Modules\Inventory\Models\Inventory;
use App\Modules\Inventory\Models\InventoryTransaction;
use App\Modules\Inventory\Models\WarehouseProductSafetyStock;
use App\Modules\Inventory\Imports\InventoryImport;
use App\Modules\Inventory\Exports\InventoryTemplateExport;
use Maatwebsite\Excel\Facades\Excel;
use Symfony\Component\HttpFoundation\BinaryFileResponse;

use App\Modules\Core\Contracts\CoreServiceInterface;

class InventoryController extends Controller
{
    protected $coreService;

    public function __construct(CoreServiceInterface $coreService)
    {
        $this->coreService = $coreService;
    }

    public function index(Request $request, Warehouse $warehouse)
    {
        // ... (existing code for index) ...
        $warehouse->load([
            'inventories.product.category',
            'inventories.product.baseUnit',
            'inventories.lastIncomingTransaction',
            'inventories.lastOutgoingTransaction'
        ]);
        $allProducts = Product::with('category')->get();

        // 1. 準備 availableProducts
        $availableProducts = $allProducts->map(function ($product) {
            return [
                'id' => (string) $product->id,
                'name' => $product->name,
                'type' => $product->category?->name ?? '其他',
            ];
        });

        // 2. 從新表格讀取安全庫存設定 (商品-倉庫層級)
        $safetyStockMap = WarehouseProductSafetyStock::where('warehouse_id', $warehouse->id)
            ->pluck('safety_stock', 'product_id')
            ->mapWithKeys(fn($val, $key) => [(string)$key => (float)$val]);

        $items = $warehouse->inventories()
            ->with(['product.baseUnit', 'lastIncomingTransaction', 'lastOutgoingTransaction'])
            ->get();

        // 判斷是否為販賣機並調整分組
        $isVending = $warehouse->type === 'vending';
        
        $inventories = $items->groupBy(function ($item) use ($isVending) {
            return $isVending 
                ? $item->product_id . '-' . ($item->location ?? 'NO-SLOT') 
                : $item->product_id;
        })->map(function ($batchItems) use ($safetyStockMap, $isVending) {
            $firstItem = $batchItems->first();
            $product = $firstItem->product;
            $totalQuantity = $batchItems->sum('quantity');
            $totalValue = $batchItems->sum('total_value'); // 計算總價值

            // 從獨立表格讀取安全庫存
            $safetyStock = $safetyStockMap[(string)$firstItem->product_id] ?? null;

            // 計算狀態
            $status = '正常';
            if (!is_null($safetyStock)) {
                if ($totalQuantity < $safetyStock) {
                    $status = '低於';
                }
            }

            return [
                'productId' => (string) $firstItem->product_id,
                'productName' => $product?->name ?? '未知商品',
                'productCode' => $product?->code ?? 'N/A',
                'baseUnit' => $product?->baseUnit?->name ?? '個',
                'totalQuantity' => (float) $totalQuantity,
                'totalValue' => (float) $totalValue,
                'safetyStock' => $safetyStock,
                'status' => $status,
                'batches' => $batchItems->map(function ($inv) {
                    return [
                        'id' => (string) $inv->id,
                        'warehouseId' => (string) $inv->warehouse_id,
                        'productId' => (string) $inv->product_id,
                        'productName' => $inv->product?->name ?? '未知商品',
                        'productCode' => $inv->product?->code ?? 'N/A',
                        'unit' => $inv->product?->baseUnit?->name ?? '個',
                        'quantity' => (float) $inv->quantity,
                        'unit_cost' => (float) $inv->unit_cost,
                        'total_value' => (float) $inv->total_value,
                        'safetyStock' => null, // 批號層級不再有安全庫存
                        'status' => '正常',
                        'batchNumber' => $inv->batch_number ?? 'BATCH-' . $inv->id,
                        'location' => $inv->location,
                        'expiryDate' => $inv->expiry_date ? $inv->expiry_date->format('Y-m-d') : null,
                        'lastInboundDate' => $inv->lastIncomingTransaction ? ($inv->lastIncomingTransaction->actual_time ? substr($inv->lastIncomingTransaction->actual_time, 0, 10) : $inv->lastIncomingTransaction->created_at->format('Y-m-d')) : null,
                        'lastOutboundDate' => $inv->lastOutgoingTransaction ? ($inv->lastOutgoingTransaction->actual_time ? substr($inv->lastOutgoingTransaction->actual_time, 0, 10) : $inv->lastOutgoingTransaction->created_at->format('Y-m-d')) : null,
                    ];
                })->values(),
            ];
        })->values();

        // 4. 準備 safetyStockSettings (從新表格讀取)
        $safetyStockSettings = WarehouseProductSafetyStock::where('warehouse_id', $warehouse->id)
            ->with(['product.category'])
            ->get()
            ->map(function ($setting) {
                return [
                    'id' => (string) $setting->id,
                    'warehouseId' => (string) $setting->warehouse_id,
                    'productId' => (string) $setting->product_id,
                    'productName' => $setting->product?->name ?? '未知商品',
                    'productType' => $setting->product?->category?->name ?? '其他',
                    'safetyStock' => (float) $setting->safety_stock,
                    'createdAt' => $setting->created_at->toIso8601String(),
                    'updatedAt' => $setting->updated_at->toIso8601String(),
                ];
            });

        return Inertia::render('Warehouse/Inventory', [
            'warehouse' => $warehouse,
            'inventories' => $inventories,
            'safetyStockSettings' => $safetyStockSettings,
            'availableProducts' => $availableProducts,
        ]);
    }

    public function create(Warehouse $warehouse)
    {
       // ... (unchanged) ...
        $products = Product::with(['baseUnit', 'largeUnit'])
            ->select('id', 'name', 'code', 'barcode', 'base_unit_id', 'large_unit_id', 'conversion_rate', 'cost_price')
            ->get()
            ->map(function ($product) {
            return [
                'id' => (string) $product->id,
                'name' => $product->name,
                'code' => $product->code,
                'barcode' => $product->barcode,
                'baseUnit' => $product->baseUnit?->name ?? '個',
                'largeUnit' => $product->largeUnit?->name, // 可能為 null
                'conversionRate' => (float) $product->conversion_rate,
                'costPrice' => (float) $product->cost_price,
            ];
        });

        return Inertia::render('Warehouse/AddInventory', [
            'warehouse' => $warehouse,
            'products' => $products,
        ]);
    }

    public function store(Request $request, Warehouse $warehouse)
    {
        // ... (unchanged) ...
        $validated = $request->validate([
            'inboundDate' => 'required|date',
            'reason' => 'required|string',
            'notes' => 'nullable|string',
            'items' => 'required|array|min:1',
            'items.*.productId' => 'required|exists:products,id',
            'items.*.quantity' => 'required|numeric|min:0.01',
            'items.*.unit_cost' => 'nullable|numeric|min:0', // 新增成本驗證
            'items.*.batchMode' => 'required|in:existing,new,none',
            'items.*.inventoryId' => 'required_if:items.*.batchMode,existing|nullable|exists:inventories,id',
            'items.*.originCountry' => 'required_if:items.*.batchMode,new|nullable|string|max:2',
            'items.*.expiryDate' => 'nullable|date',
            'items.*.location' => 'nullable|string|max:50',
        ]);

        return DB::transaction(function () use ($validated, $warehouse) {
            foreach ($validated['items'] as $item) {
                // ... (略，傳遞 unit_cost 交給 Service 處理) ...
                // 這裡需要修改呼叫 Service 的地方或直接更新邏輯
                // 為求快速，我將在此更新邏輯
                
                $inventory = null;

                if ($item['batchMode'] === 'existing') {
                    // 模式 A：選擇現有批號 (包含已刪除的也要能找回來累加)
                    $inventory = Inventory::withTrashed()->findOrFail($item['inventoryId']);
                    if ($inventory->trashed()) {
                        $inventory->restore();
                    }
                    
                    // 更新成本 (若有傳入)
                    if (isset($item['unit_cost'])) {
                        $inventory->unit_cost = $item['unit_cost'];
                    }
                } elseif ($item['batchMode'] === 'none') {
                    // 模式 C：不使用批號 (自動累加至 NO-BATCH)
                    $inventory = $warehouse->inventories()->withTrashed()->firstOrNew(
                        [
                            'product_id' => $item['productId'],
                            'batch_number' => 'NO-BATCH'
                        ],
                        [
                            'quantity' => 0,
                            'unit_cost' => $item['unit_cost'] ?? 0,
                            'total_value' => 0,
                            'arrival_date' => $validated['inboundDate'],
                            'expiry_date' => null,
                            'origin_country' => 'TW',
                        ]
                    );

                    if ($inventory->trashed()) {
                        $inventory->restore();
                    }
                } else {
                    // 模式 B：建立新批號
                    $originCountry = $item['originCountry'] ?? 'TW';
                    $product = Product::find($item['productId']);
                    
                    $batchNumber = Inventory::generateBatchNumber(
                        $product->code ?? 'UNK',
                        $originCountry,
                        $validated['inboundDate']
                    );

                    // 檢查是否存在
                    $inventory = $warehouse->inventories()->withTrashed()->firstOrNew(
                        [
                            'product_id' => $item['productId'],
                            'batch_number' => $batchNumber
                        ],
                        [
                            'quantity' => 0,
                            'unit_cost' => $item['unit_cost'] ?? 0, // 新增
                            'total_value' => 0, // 稍後計算
                            'location' => $item['location'] ?? null,
                            'arrival_date' => $validated['inboundDate'],
                            'expiry_date' => $item['expiryDate'] ?? null,
                            'origin_country' => $originCountry,
                        ]
                    );

                    if ($inventory->trashed()) {
                        $inventory->restore();
                    }
                }

                $currentQty = $inventory->quantity;
                $newQty = $currentQty + $item['quantity'];

                $inventory->quantity = $newQty;
                // 更新總價值
                $inventory->total_value = $inventory->quantity * $inventory->unit_cost;
                $inventory->save();

                // 寫入異動紀錄
                $inventory->transactions()->create([
                    'type' => '手動入庫',
                    'quantity' => $item['quantity'],
                    'unit_cost' => $inventory->unit_cost, // 記錄成本
                    'balance_before' => $currentQty,
                    'balance_after' => $newQty,
                    'reason' => $validated['reason'] . ($validated['notes'] ? ' - ' . $validated['notes'] : ''),
                    'actual_time' => $validated['inboundDate'],
                    'user_id' => auth()->id(),
                ]);
            }

            return redirect()->route('warehouses.inventory.index', $warehouse->id)
                ->with('success', '庫存記錄已儲存成功');
        });
    }

    // ... (getBatches unchanged) ...
    public function getBatches(Warehouse $warehouse, $productId, Request $request)
    {
        $originCountry = $request->query('originCountry', 'TW');
        $arrivalDate = $request->query('arrivalDate', now()->format('Y-m-d'));

        $batches = Inventory::where('warehouse_id', $warehouse->id)
            ->where('product_id', $productId)
            ->get()
            ->map(function ($inventory) {
                return [
                    'inventoryId' => (string) $inventory->id,
                    'batchNumber' => $inventory->batch_number,
                    'originCountry' => $inventory->origin_country,
                    'expiryDate' => $inventory->expiry_date ? $inventory->expiry_date->format('Y-m-d') : null,
                    'quantity' => (float) $inventory->quantity,
                    'unitCost' => (float) $inventory->unit_cost,
                    'location' => $inventory->location,
                ];
            });

        // 計算下一個流水號
        $product = Product::find($productId);
        $nextSequence = '01';
        if ($product) {
            $batchNumber = Inventory::generateBatchNumber(
                $product->code ?? 'UNK',
                $originCountry,
                $arrivalDate
            );
            $nextSequence = substr($batchNumber, -2);
        }

        return response()->json([
            'batches' => $batches,
            'nextSequence' => $nextSequence
        ]);
    }


    public function edit(Request $request, Warehouse $warehouse, $inventoryId)
    {
        if (str_starts_with($inventoryId, 'mock-inv-')) {
             return redirect()->back()->with('error', '無法編輯範例資料');
        }

        // 移除 'transactions.user' 預載入
        $inventory = Inventory::with(['product', 'transactions' => function($query) {
            $query->orderBy('actual_time', 'desc')->orderBy('id', 'desc');
        }])->findOrFail($inventoryId);

        // 手動 Hydrate 使用者資料
        $userIds = $inventory->transactions->pluck('user_id')->filter()->unique()->toArray();
        $users = $this->coreService->getUsersByIds($userIds)->keyBy('id');

        // 轉換為前端需要的格式
        $inventoryData = [
            'id' => (string) $inventory->id,
            'warehouseId' => (string) $inventory->warehouse_id,
            'productId' => (string) $inventory->product_id,
            'productName' => $inventory->product?->name ?? '未知商品',
            'quantity' => (float) $inventory->quantity,
            'unit_cost' => (float) $inventory->unit_cost,
            'total_value' => (float) $inventory->total_value,
            'batchNumber' => $inventory->batch_number ?? '-',
            'expiryDate' => $inventory->expiry_date ?? null,
            'lastInboundDate' => $inventory->updated_at->format('Y-m-d'),
            'lastOutboundDate' => null,
        ];

        // 整理異動紀錄
        $transactions = $inventory->transactions->map(function ($tx) use ($users) {
            $user = $tx->user_id ? ($users[$tx->user_id] ?? null) : null;
            return [
                'id' => (string) $tx->id,
                'type' => $tx->type,
                'quantity' => (float) $tx->quantity,
                'unit_cost' => (float) $tx->unit_cost,
                'balanceAfter' => (float) $tx->balance_after,
                'reason' => $tx->reason,
                'userName' => $user ? $user->name : '系統', // 手動對應
                'actualTime' => $tx->actual_time ? substr($tx->actual_time, 0, 16) : $tx->created_at->format('Y-m-d H:i'),
            ];
        });

        return Inertia::render('Warehouse/EditInventory', [
            'warehouse' => $warehouse,
            'inventory' => $inventoryData,
            'transactions' => $transactions,
        ]);
    }

    public function update(Request $request, Warehouse $warehouse, $inventoryId)
    {
        // ... (unchanged) ...
        $inventory = Inventory::find($inventoryId);
        
        // 如果找不到 (可能是舊路由傳 product ID)
        if (!$inventory) {
             $inventory = $warehouse->inventories()->where('product_id', $inventoryId)->first();
        }

        if (!$inventory) {
            return redirect()->back()->with('error', '找不到庫存紀錄');
        }

        $validated = $request->validate([
            'quantity' => 'required|numeric|min:0',
            // 以下欄位改為 nullable，支援新表單
            'type' => 'nullable|string',
            'operation' => 'nullable|in:add,subtract,set',
            'reason' => 'nullable|string',
            'notes' => 'nullable|string',
            'unit_cost' => 'nullable|numeric|min:0', // 新增成本
            // ...
            'batchNumber' => 'nullable|string',
            'expiryDate' => 'nullable|date',
            'lastInboundDate' => 'nullable|date',
            'lastOutboundDate' => 'nullable|date',
        ]);

        return DB::transaction(function () use ($validated, $inventory) {
            $currentQty = (float) $inventory->quantity;
            $newQty = (float) $validated['quantity'];
            
            // 判斷是否來自調整彈窗 (包含 operation 參數)
            $isAdjustment = isset($validated['operation']);
            $changeQty = 0;

            if ($isAdjustment) {
                switch ($validated['operation']) {
                    case 'add':
                        $changeQty = (float) $validated['quantity'];
                        $newQty = $currentQty + $changeQty;
                        break;
                    case 'subtract':
                        $changeQty = -(float) $validated['quantity'];
                        $newQty = $currentQty + $changeQty;
                        break;
                    case 'set':
                        $changeQty = $newQty - $currentQty;
                        break;
                }
            } else {
                // 來自編輯頁面，直接 Set
                $changeQty = $newQty - $currentQty;
            }

            // 更新成本 (若有傳)
            if (isset($validated['unit_cost'])) {
                $inventory->unit_cost = $validated['unit_cost'];
            }

            // 更新庫存
            $inventory->quantity = $newQty;
            // 更新總值
            $inventory->total_value = $inventory->quantity * $inventory->unit_cost;
            $inventory->save();

            // 異動類型映射
            $type = $validated['type'] ?? ($isAdjustment ? 'manual_adjustment' : 'adjustment');
            $typeMapping = [
                'manual_adjustment' => '手動調整庫存',
                'adjustment' => '盤點調整',
                'purchase_in' => '採購進貨',
                'sales_out' => '銷售出庫',
                'return_in' => '退貨入庫',
                'return_out' => '退貨出庫',
                'transfer_in' => '撥補入庫',
                'transfer_out' => '撥補出庫',
            ];
            $chineseType = $typeMapping[$type] ?? $type;
            
            // 如果是編輯頁面來的，且沒傳 type，設為手動編輯
            if (!$isAdjustment && !isset($validated['type'])) {
                $chineseType = '手動編輯';
            }

            // 整理原因
            $reason = $validated['reason'] ?? ($isAdjustment ? '手動庫存調整' : '編輯頁面更新');
            if (isset($validated['notes'])) {
                $reason .= ' - ' . $validated['notes'];
            }

            // 寫入異動紀錄
            if (abs($changeQty) > 0.0001) {
                $inventory->transactions()->create([
                    'type' => $chineseType,
                    'quantity' => $changeQty,
                    'unit_cost' => $inventory->unit_cost, // 記錄
                    'balance_before' => $currentQty,
                    'balance_after' => $newQty,
                    'reason' => $reason,
                    'actual_time' => now(), 
                    'user_id' => auth()->id(),
                ]);
            }

            return redirect()->route('warehouses.inventory.index', $inventory->warehouse_id)
                ->with('success', '庫存資料已更新');
        });
    }

    public function destroy(Warehouse $warehouse, $inventoryId)
    {
         // ... (unchanged) ...
          $inventory = Inventory::findOrFail($inventoryId);
         
         // 庫存 > 0 不允許刪除 (哪怕是軟刪除)
         if ($inventory->quantity > 0) {
             return redirect()->back()->with('error', '庫存數量大於 0，無法刪除。請先進行出庫或調整。');
         }
         
         // 歸零異動 (因為已經限制為 0 才能刪，這段邏輯可以簡化，但為了保險起見，若有微小殘值仍可記錄歸零)
         if (abs($inventory->quantity) > 0.0001) {
             $inventory->transactions()->create([
                    'type' => '手動編輯',
                    'quantity' => -$inventory->quantity,
                    'unit_cost' => $inventory->unit_cost,
                    'balance_before' => $inventory->quantity,
                    'balance_after' => 0,
                    'reason' => '刪除庫存品項',
                    'actual_time' => now(),
                    'user_id' => auth()->id(),
             ]);
         }
         
         $inventory->delete();
         
         return redirect()->route('warehouses.inventory.index', $warehouse->id)
                ->with('success', '庫存品項已刪除');
    }

    public function history(Request $request, \App\Modules\Inventory\Models\Warehouse $warehouse)
    {
        // ... (前端 history 頁面可能也需要 unit_cost，這裡可補上) ...
        $inventoryId = $request->query('inventoryId');
        $productId = $request->query('productId');

        if ($productId) {
            $product = Product::findOrFail($productId);
            // 取得該倉庫中該商品的所有批號 ID
            $inventoryIds = Inventory::where('warehouse_id', $warehouse->id)
                ->where('product_id', $productId)
                ->pluck('id')
                ->toArray();

            $transactionsRaw = InventoryTransaction::whereIn('inventory_id', $inventoryIds)
                ->with('inventory') // 需要批號資訊
                ->orderBy('actual_time', 'desc')
                ->orderBy('id', 'desc')
                ->get();

            // 手動 Hydrate 使用者資料
            $userIds = $transactionsRaw->pluck('user_id')->filter()->unique()->toArray();
            $users = $this->coreService->getUsersByIds($userIds)->keyBy('id');

            // 計算商品在該倉庫的總量（不分批號）
            $currentRunningTotal = (float) Inventory::whereIn('id', $inventoryIds)->sum('quantity');

            $transactions = $transactionsRaw->map(function ($tx) use ($users, &$currentRunningTotal) {
                $user = $tx->user_id ? ($users[$tx->user_id] ?? null) : null;
                $balanceAfter = $currentRunningTotal;
                
                // 為下一筆（較舊的）紀錄更新 Running Total
                $currentRunningTotal -= (float) $tx->quantity;

                return [
                    'id' => (string) $tx->id,
                    'type' => $tx->type,
                    'quantity' => (float) $tx->quantity,
                    'unit_cost' => (float) $tx->unit_cost, 
                    'balanceAfter' => (float) $balanceAfter, // 顯示該商品在倉庫的累計結餘
                    'reason' => $tx->reason,
                    'userName' => $user ? $user->name : '系統',
                    'actualTime' => $tx->actual_time ? substr($tx->actual_time, 0, 16) : $tx->created_at->format('Y-m-d H:i'),
                    'batchNumber' => $tx->inventory?->batch_number ?? '-', // 補上批號資訊
                    'slot' => $tx->inventory?->location, // 加入貨道資訊
                ];
            });

            // 重新計算目前的總量（用於 Header 顯示，確保一致性）
            $totalQuantity = Inventory::whereIn('id', $inventoryIds)->sum('quantity');

            return Inertia::render('Warehouse/InventoryHistory', [
                'warehouse' => $warehouse,
                'inventory' => [
                    'id' => null, // 跨批號查詢沒有單一 ID
                    'productName' => $product->name,
                    'productCode' => $product->code,
                    'batchNumber' => '所有批號',
                    'quantity' => (float) $totalQuantity,
                ],
                'transactions' => $transactions
            ]);
        }

        if ($inventoryId) {
            // 單一批號查詢
            // 移除 'transactions.user'
            $inventory = Inventory::with(['product', 'transactions' => function($query) {
                $query->orderBy('actual_time', 'desc')->orderBy('id', 'desc');
            }])->findOrFail($inventoryId);

            // 手動 Hydrate 使用者資料
            $userIds = $inventory->transactions->pluck('user_id')->filter()->unique()->toArray();
            $users = $this->coreService->getUsersByIds($userIds)->keyBy('id');

            $transactions = $inventory->transactions->map(function ($tx) use ($users, $inventory) {
                $user = $tx->user_id ? ($users[$tx->user_id] ?? null) : null;
                return [
                    'id' => (string) $tx->id,
                    'type' => $tx->type,
                    'quantity' => (float) $tx->quantity,
                    'unit_cost' => (float) $tx->unit_cost, 
                    'balanceAfter' => (float) $tx->balance_after,
                    'reason' => $tx->reason,
                    'userName' => $user ? $user->name : '系統', // 手動對應
                    'actualTime' => $tx->actual_time ? substr($tx->actual_time, 0, 16) : $tx->created_at->format('Y-m-d H:i'),
                    'slot' => $inventory->location, // 加入貨道資訊
                ];
            });

            return Inertia::render('Warehouse/InventoryHistory', [
                'warehouse' => $warehouse,
                'inventory' => [
                    'id' => (string) $inventory->id,
                    'productName' => $inventory->product?->name ?? '未知商品',
                    'productCode' => $inventory->product?->code ?? 'N/A',
                    'batchNumber' => $inventory->batch_number ?? '-',
                    'quantity' => (float) $inventory->quantity,
                    'unit_cost' => (float) $inventory->unit_cost,
                    'total_value' => (float) $inventory->total_value,
                ],
                'transactions' => $transactions
            ]);
        }

        return redirect()->back()->with('error', '未提供查詢參數');
    }

    /**
     * 匯入入庫
     */
    public function import(Request $request, Warehouse $warehouse)
    {
        $request->validate([
            'file' => 'required|mimes:xlsx,xls,csv',
            'inboundDate' => 'required|date',
            'notes' => 'nullable|string',
        ]);

        try {
            Excel::import(
                new InventoryImport($warehouse, $request->inboundDate, $request->notes),
                $request->file('file')
            );

            return back()->with('success', '庫存資料匯入成功');
        } catch (\Exception $e) {
            return back()->withErrors(['file' => '匯入過程中發生錯誤: ' . $e->getMessage()]);
        }
    }

    /**
     * 下載匯入範本 (.xlsx)
     */
    public function template()
    {
        return Excel::download(new InventoryTemplateExport, '庫存匯入範本.xlsx');
    }
}
