<?php

namespace App\Filament\Resources\SalesOrderResource\Concerns;

use App\Models\Inventory\StockBatch;
use App\Models\Scopes\BranchScope;
use App\Services\BatchService;
use App\Services\CurrentContext;

trait ResolvesOrderProductLots
{
    /**
     * Live lot lookup for the Sales Order product grid.
     *
     * Rules:
     *
     * 1. If a sellable lot exists:
     *      return the real sellable lot(s).
     *
     * 2. If no sellable lot exists:
     *      return ONE virtual quotation lot.
     *
     *      The virtual lot:
     *          id = null
     *          price = latest active priced batch
     *          available = 0
     *
     *      This allows an out-of-stock product to be quoted
     *      without claiming a real stock batch.
     *
     * 3. If no priced batch exists:
     *      return [].
     */
    public function orderProductLots(int $productId): array
    {
        $formBranchId = (int) ($this->form->getRawState()['branch_id'] ?? 0);

        $branchId = $formBranchId
            ?: app(CurrentContext::class)->branchId();

        abort_unless($branchId, 409, 'Pick a branch first.');

        /*
         * -------------------------------------------------------------
         * 1. REAL SELLABLE LOTS
         * -------------------------------------------------------------
         */
        $lots = app(BatchService::class)
            ->sellableFor($productId, $branchId)
            ->map(fn (StockBatch $lot): array => [
                'id' => $lot->id,
                'batch' => $lot->internal_batch_number,
                'price' => (float) $lot->sale_price,
                'cost' => $lot->batch_cost !== null
                    ? (float) $lot->batch_cost
                    : null,
                'expiry' => $lot->expiry_date?->toDateString(),
                'available' => (float) $lot->available_quantity,

                /*
                 * IMPORTANT:
                 *
                 * This is a REAL fulfilment lot.
                 */
                'is_quote_only' => false,
            ])
            ->values()
            ->all();

        if ($lots !== []) {
            return $lots;
        }

        /*
         * -------------------------------------------------------------
         * 2. NO SELLABLE STOCK
         *
         * Find the latest active priced batch purely for quotation.
         * Do NOT expose its ID as the selected batch.
         * -------------------------------------------------------------
         */
        $quoteLot = StockBatch::query()
            ->withoutGlobalScope(BranchScope::class)
            ->where('product_id', $productId)
            ->where('branch_id', $branchId)
            ->active()
            ->whereNotNull('sale_price')
            ->orderByDesc('created_at')
            ->first();

        /*
         * -------------------------------------------------------------
         * 3. NO PRICE AT ALL
         * -------------------------------------------------------------
         */
        if (! $quoteLot) {
            return [];
        }

        /*
         * -------------------------------------------------------------
         * 4. VIRTUAL QUOTATION LOT
         *
         * id = null is CRITICAL.
         *
         * This prevents SalesOrderService from interpreting this
         * historical batch as the fulfilment batch.
         * -------------------------------------------------------------
         */
        return [
            [
                'id' => null,
                'batch' => null,
                'price' => (float) $quoteLot->sale_price,
                'cost' => $quoteLot->batch_cost !== null
                    ? (float) $quoteLot->batch_cost
                    : null,
                'expiry' => null,
                'available' => 0.0,

                /*
                 * Tells the frontend:
                 *
                 * "This price is only for quotation."
                 */
                'is_quote_only' => true,
            ],
        ];
    }
}