<?php
namespace App\Modules\Inventory\Services;

use App\Modules\Inventory\Models\Inventory;
use App\Modules\Inventory\Models\InventoryCountDoc;
use App\Modules\Inventory\Models\InventoryAdjustDoc;
use App\Modules\Inventory\Models\InventoryAdjustItem;
use Illuminate\Support\Facades\DB;

class AdjustService
{
    public function createDoc(string $warehouseId, string $reason, ?string $remarks = null, int $userId, ?int $countDocId = null): InventoryAdjustDoc
    {
        return InventoryAdjustDoc::create([
            'warehouse_id' => $warehouseId,
            'count_doc_id' => $countDocId,
            'status' => 'draft',
            'reason' => $reason,
            'remarks' => $remarks,
            'created_by' => $userId,
        ]);
    }

    /**
     * 從盤點單建立盤調單
     */
    public function createFromCountDoc(InventoryCountDoc $countDoc, int $userId): InventoryAdjustDoc
    {
        return DB::transaction(function () use ($countDoc, $userId) {
            // 1. 建立盤調單頭
            $adjDoc = $this->createDoc(
                $countDoc->warehouse_id,
                "盤點調整: " . $countDoc->doc_no,
                "由盤點單 {$countDoc->doc_no} 自動生成",
                $userId,
                $countDoc->id
            );

            // 2. 抓取有差異的明細 (diff_qty != 0)
            foreach ($countDoc->items as $item) {
                if (abs($item->diff_qty) < 0.0001) continue;

                $adjDoc->items()->create([
                    'product_id' => $item->product_id,
                    'batch_number' => $item->batch_number,
                    'qty_before' => $item->system_qty,
                    'adjust_qty' => $item->diff_qty,
                    'notes' => "盤點差異: " . $item->diff_qty,
                ]);
            }

            return $adjDoc;
        });
    }

    /**
     * 更新盤調單內容 (Items)
     * 此處採用 "全量更新" 方式處理 items (先刪後加)，簡單可靠
     */
    public function updateItems(InventoryAdjustDoc $doc, array $itemsData): void
    {
        DB::transaction(function () use ($doc, $itemsData) {
            $updatedItems = [];
            $oldItems = $doc->items()->with('product')->get();
            
            // 記錄舊品項狀態 (用於標註異動)
            foreach ($oldItems as $oldItem) {
                $updatedItems[] = [
                    'product_name' => $oldItem->product->name,
                    'old' => [
                        'adjust_qty' => (float)$oldItem->adjust_qty,
                        'notes' => $oldItem->notes,
                    ],
                    'new' => null // 標記為刪除或待更新
                ];
            }

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

            foreach ($itemsData as $data) {
                // 取得當前庫存作為 qty_before 參考 (僅參考，實際扣減以過帳當下為準)
                $inventory = Inventory::where('warehouse_id', $doc->warehouse_id)
                    ->where('product_id', $data['product_id'])
                    ->where('batch_number', $data['batch_number'] ?? null)
                    ->first();
                
                $qtyBefore = $inventory ? $inventory->quantity : 0;

                $newItem = $doc->items()->create([
                    'product_id' => $data['product_id'],
                    'batch_number' => $data['batch_number'] ?? null,
                    'qty_before' => $qtyBefore,
                    'adjust_qty' => $data['adjust_qty'],
                    'notes' => $data['notes'] ?? null,
                ]);

                // 更新日誌中的品項列表
                $productName = \App\Modules\Inventory\Models\Product::find($data['product_id'])?->name;
                $found = false;
                foreach ($updatedItems as $idx => $ui) {
                    if ($ui['product_name'] === $productName && $ui['new'] === null) {
                        $updatedItems[$idx]['new'] = [
                            'adjust_qty' => (float)$data['adjust_qty'],
                            'notes' => $data['notes'] ?? null,
                        ];
                        $found = true;
                        break;
                    }
                }
                if (!$found) {
                    $updatedItems[] = [
                        'product_name' => $productName,
                        'old' => null,
                        'new' => [
                            'adjust_qty' => (float)$data['adjust_qty'],
                            'notes' => $data['notes'] ?? null,
                        ]
                    ];
                }
            }

            // 清理沒被更新到的舊品項 (即真正被刪除的)
            $finalUpdatedItems = [];
            foreach ($updatedItems as $ui) {
                if ($ui['old'] === null && $ui['new'] === null) continue;
                // 比對是否有實質變動
                if ($ui['old'] != $ui['new']) {
                    $finalUpdatedItems[] = $ui;
                }
            }

            if (!empty($finalUpdatedItems)) {
                activity()
                    ->performedOn($doc)
                    ->causedBy(auth()->user())
                    ->event('updated')
                    ->withProperties([
                        'items_diff' => [
                            'updated' => $finalUpdatedItems,
                        ]
                    ])
                    ->log('updated');
            }
        });
    }

    /**
     * 過帳 (Post) - 生效庫存異動
     */
    public function post(InventoryAdjustDoc $doc, int $userId): void
    {
        DB::transaction(function () use ($doc, $userId) {
            $oldStatus = $doc->status;
            
            foreach ($doc->items as $item) {
                if ($item->adjust_qty == 0) continue;

                $inventory = Inventory::firstOrNew([
                    'warehouse_id' => $doc->warehouse_id,
                    'product_id' => $item->product_id,
                    'batch_number' => $item->batch_number,
                ]);

                // 如果是新建立的 object (id 為空)，需要初始化 default
                if (!$inventory->exists) {
                     $inventory->unit_cost = $item->product->cost ?? 0;
                     $inventory->quantity = 0; 
                }

                $oldQty = $inventory->quantity;
                $newQty = $oldQty + $item->adjust_qty;
                
                $inventory->quantity = $newQty;
                $inventory->total_value = $newQty * $inventory->unit_cost;
                $inventory->save();

                // 建立 Transaction
                $inventory->transactions()->create([
                    'type' => '庫存調整',
                    'quantity' => $item->adjust_qty,
                    'unit_cost' => $inventory->unit_cost,
                    'balance_before' => $oldQty,
                    'balance_after' => $newQty,
                    'reason' => "盤調單 {$doc->doc_no}: " . ($doc->reason ?? '手動調整'),
                    'actual_time' => now(),
                    'user_id' => $userId,
                ]);
            }

            // 使用 saveQuietly 避免重複產生自動日誌
            $doc->status = 'posted';
            $doc->posted_at = now();
            $doc->posted_by = $userId;
            $doc->saveQuietly();

            // 準備品項快照供日誌使用
            $itemsSnapshot = $doc->items->map(function($item) {
                return [
                    'product_name' => $item->product->name,
                    'old' => null, // 過帳視為整單生效，不顯示個別欄位差異
                    'new' => [
                        'adjust_qty' => (float)$item->adjust_qty,
                        'notes' => $item->notes,
                    ]
                ];
            })->toArray();

            // 手動產生過帳日誌
            activity()
                ->performedOn($doc)
                ->causedBy(auth()->user())
                ->event('updated')
                ->withProperties([
                    'attributes' => [
                        'status' => 'posted',
                        'posted_at' => $doc->posted_at->format('Y-m-d H:i:s'),
                        'posted_by' => $userId,
                    ],
                    'old' => [
                        'status' => $oldStatus,
                        'posted_at' => null,
                        'posted_by' => null,
                    ],
                    'items_diff' => [
                        'updated' => $itemsSnapshot,
                    ]
                ])
                ->log('posted');

            // 4. 若關聯盤點單，連動更新盤點單狀態
            if ($doc->count_doc_id) {
                $countDoc = InventoryCountDoc::find($doc->count_doc_id);
                if ($countDoc) {
                    $countDoc->status = 'adjusted';
                    $countDoc->saveQuietly(); // 盤點單也靜默更新
                }
            }
        });
    }
    
    /**
     * 作廢 (Void)
     */
    public function void(InventoryAdjustDoc $doc, int $userId): void 
    {
         if ($doc->status !== 'draft') {
             throw new \Exception('只能作廢草稿狀態的單據');
         }

         $oldStatus = $doc->status;
         $doc->status = 'voided';
         $doc->updated_by = $userId;
         $doc->saveQuietly();

         activity()
            ->performedOn($doc)
            ->causedBy(auth()->user())
            ->event('updated')
            ->withProperties([
                'attributes' => ['status' => 'voided'],
                'old' => ['status' => $oldStatus]
            ])
            ->log('voided');
    }
}
