<?php

namespace App\Services;

use App\Models\Account;
use App\Models\AccountTransaction;
use App\Models\ChartOfAccount;
use App\Models\Qc;
use App\Models\QcItem;
use App\Models\PurchaseOrderItem;
use App\Models\Stock;
use App\Models\StockLedger;
use App\Models\WeightedAveragePriceHistory;
use Illuminate\Support\Facades\DB;

class StockAccountingService
{
    /**
     * Handle QC event with double-entry accounting
     */
    public function handleQcEvent(Qc $qc): void
    {
        DB::transaction(function () use ($qc) {
            // Get QC items with accepted quantities
            $qcItems = QcItem::where('qc_id', $qc->id)
                ->where('accepted_qty', '>', 0)
                ->get();

            foreach ($qcItems as $qcItem) {
                $this->processQcItem($qc, $qcItem);
            }

            // Update QC status to indicate stock has been added
            $qc->update(['stock_added' => true]);
        });
    }

    /**
     * Process individual QC item
     */
    // private function processQcItem(Qc $qc, QcItem $qcItem): void
    // {
    //     // Get purchase order item for unit price
    //     $poItem = PurchaseOrderItem::find($qcItem->purchase_order_item_id);
    //     if (!$poItem) {
    //         throw new \Exception("Purchase order item not found for QC item ID: {$qcItem->id}");
    //     }

    //     $acceptedQty = $qcItem->accepted_qty;
    //     $unitPrice = $poItem->unit_price;
    //     $totalAmount = $acceptedQty * $unitPrice;

    //     // Get inventory account (item account)
    //     $inventoryAccount = Account::where('id', $qcItem->item_id)
    //         ->where('model_type', 'Item')
    //         ->first();

    //     if (!$inventoryAccount) {
    //         throw new \Exception("Inventory account not found for item ID: {$qcItem->item_id}");
    //     }

    //     // Get supplier account from purchase order
    //     $po = $poItem->purchaseOrder;
    //     // dd($po);
    //     $supplierAccount = Account::where('id', $po->contact_id)
    //         ->where('model_type', 'supplier')
    //         ->first();

    //     if (!$supplierAccount) {
    //         throw new \Exception("Supplier account not found for supplier ID: {$po->contact_id}");
    //     }

    //     // Update stock quantity
    //     $this->updateStock($qcItem, $acceptedQty);

    //     // Insert stock ledger entry
    //     $this->insertStockLedger($qc, $qcItem, $acceptedQty);

    //     // Create double-entry transactions
    //     $this->createDoubleEntryTransactions($qc, $inventoryAccount, $supplierAccount, $totalAmount);

    //     // Update weighted average price
    //     $this->updateWeightedAveragePrice($inventoryAccount, $acceptedQty, $unitPrice);
    // }

    private function processQcItem(Qc $qc, QcItem $qcItem): void
    {
        // Get purchase order item for unit price
        $poItem = PurchaseOrderItem::find($qcItem->purchase_order_item_id);
        if (!$poItem) {
            throw new \Exception("Purchase order item not found for QC item ID: {$qcItem->id}");
        }

        $acceptedQty = $qcItem->accepted_qty;
        $unitPrice = $poItem->unit_price;
        $totalAmount = $acceptedQty * $unitPrice;

        // ✅ Get inventory account (item account)
        $inventoryAccount = Account::where('id', $qcItem->item_id)
            ->where('model_type', 'Item')
            ->first();

        if (!$inventoryAccount) {
            throw new \Exception("Inventory account not found for item ID: {$qcItem->item_id}");
        }

        // ✅ Get supplier account from IGP → Purchase Order
        $supplierAccount = $this->getSupplierAccountFromIGP($qc->igp);

        if (!$supplierAccount) {
            throw new \Exception("Supplier account not found for IGP ID: {$qc->igp_id}");
        }

        // Validate that it's actually a supplier account
        if ($supplierAccount->model_type !== 'supplier') {
            throw new \Exception("Invalid account type for supplier. Expected 'supplier', got '{$supplierAccount->model_type}'");
        }

        // Update stock quantity (no accounting transaction)
        $this->updateStock($qcItem, $acceptedQty);

        // Insert stock ledger entry (no accounting transaction)
        $this->insertStockLedger($qc, $qcItem, $acceptedQty);

        // ✅ Create double-entry transactions (Inventory Debit, Supplier Credit)
        $this->createDoubleEntryTransactions($qc, $inventoryAccount, $supplierAccount, $totalAmount);

    // Update weighted average price (no accounting transaction)
    $this->updateWeightedAveragePriceForItem($qcItem->item_id, $acceptedQty, $unitPrice);
}


    /**
     * Update stock quantity
     */
    private function updateStock(QcItem $qcItem, float $acceptedQty): void
    {
        $stock = Stock::where('account_id', $qcItem->item_id)
            ->where('warehouse_id', $qcItem->warehouse_id)
            ->where('bin_id', $qcItem->bin_id)
            ->first();

        if ($stock) {
            $stock->increment('quantity', $acceptedQty);
        } else {
            Stock::create([
                'account_id' => $qcItem->item_id,
                'quantity' => $acceptedQty,
                'warehouse_id' => $qcItem->warehouse_id,
                'bin_id' => $qcItem->bin_id,
                'timestamp' => now(),
            ]);
        }
    }

    /**
     * Insert stock ledger entry
     */
    private function insertStockLedger(Qc $qc, QcItem $qcItem, float $acceptedQty): void
    {
        StockLedger::create([
            'qc_id' => $qc->id,
            'igp_id' => $qc->igp_id,
            'po_id' => $qc->igp->purchase_order_id,
            'account_id' => $qcItem->item_id,
            'quantity' => $acceptedQty,
            'warehouse_id' => $qcItem->warehouse_id,
            // 'bin_id' => $qcItem->bin_id,
            'remarks' => 'QC - Stock added to available inventory',
            'timestamp' => now(),
        ]);
    }

    /**
     * Get supplier account from IGP → Purchase Order (like inward gate pass)
     */
    private function getSupplierAccountFromIGP($igp): ?Account
    {
        if (!$igp || !$igp->purchaseOrder) {
            return null;
        }

        // Get supplier account through purchase order (same as IGP)
        $supplierAccount = $igp->purchaseOrder->supplier ?? $igp->purchaseOrder->vendor;

        // Ensure it's actually a supplier account
        if ($supplierAccount && $supplierAccount->model_type === 'supplier') {
            return $supplierAccount;
        }

        return null;
    }

    /**
     * Create ONLY supplier transaction (accounts payable)
     */
    /**
     * Create double-entry transactions (Inventory Debit, Supplier Credit)
     */
    private function createDoubleEntryTransactions(Qc $qc, Account $inventoryAccount, Account $supplierAccount, float $totalAmount): void
    {
        // Get chart of accounts
        $inventoryCoA = $inventoryAccount->chartOfAccount;
        $supplierCoA = $supplierAccount->chartOfAccount;

        // ✅ Debit: Inventory account (Asset increases)
        // AccountTransaction::create([
        //     'account_id' => $inventoryAccount->id,
        //     'chart_of_account_id' => $inventoryCoA->id,
        //     'amount' => $totalAmount,
        //     'transaction_type' => 'debit',
        //     'reference_id' => $qc->igp->purchaseOrder->id, // Purchase Order ID
        //     'reference_type' => 'purchase_order',
        //     'remarks' => 'Inventory increased (QC acceptance) - PO: ' . $qc->igp->purchaseOrder->po_number,
        // ]);

        // ✅ Credit: Supplier account (Liability increases)
        AccountTransaction::create([
            'account_id' => $supplierAccount->id,
            'chart_of_account_id' => $supplierCoA->id,
            'amount' => $totalAmount,
            'transaction_type' => 'credit',
            'reference_id' => $qc->igp->purchaseOrder->id, // Purchase Order ID
            'reference_type' => 'purchase_order',
            'remarks' => 'Accounts payable created (QC acceptance) - PO: ' . $qc->igp->purchaseOrder->po_number,
        ]);
    }

    /**
     * Update weighted average price for item (no accounting transaction)
     */
    private function updateWeightedAveragePriceForItem(int $itemId, float $newQty, float $newPrice): void
    {
        $inventoryAccount = Account::find($itemId);
        if (!$inventoryAccount) return;

        $oldWAP = $inventoryAccount->weighted_average_price ?? 0;
        $oldQty = $this->getCurrentStockQuantity($inventoryAccount);

        // Calculate new weighted average price
        if ($oldQty == 0) {
            $newWAP = $newPrice;
        } else {
            $newWAP = (($oldWAP * $oldQty) + ($newPrice * $newQty)) / ($oldQty + $newQty);
        }

        // Update account (no transaction created)
        $inventoryAccount->update(['weighted_average_price' => $newWAP]);

        // Insert into history (no transaction)
        WeightedAveragePriceHistory::create([
            'account_id' => $inventoryAccount->id,
            'weighted_average_price' => $newWAP,
        ]);
    }

    /**
     * ✅ COMMENTED OUT: Old weighted average price method
     */
    // private function updateWeightedAveragePrice(Account $inventoryAccount, float $newQty, float $newPrice): void
    // {
    //     $oldWAP = $inventoryAccount->weighted_average_price ?? 0;
    //     $oldQty = $this->getCurrentStockQuantity($inventoryAccount);

    //     // Calculate new weighted average price
    //     if ($oldQty == 0) {
    //         $newWAP = $newPrice;
    //     } else {
    //         $newWAP = (($oldWAP * $oldQty) + ($newPrice * $newQty)) / ($oldQty + $newQty);
    //     }

    //     // Update account
    //     $inventoryAccount->update(['weighted_average_price' => $newWAP]);

    //     // Insert into history
    //     WeightedAveragePriceHistory::create([
    //         'account_id' => $inventoryAccount->id,
    //         'weighted_average_price' => $newWAP,
    //     ]);
    // }

    /**
     * Get current stock quantity for an item
     */
    private function getCurrentStockQuantity(Account $inventoryAccount): float
    {
        return Stock::where('account_id', $inventoryAccount->id)->sum('quantity');
    }
}
