<?php

namespace App\Services;

use App\Jobs\SetStockLog;
use App\Models\OPERATION\Operation;
use App\Models\STOCK\Stocklog;
use App\Models\STOCK\Immobilisation;
use App\Models\PRODUCT\Product;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Str;

class StockLogsHandler
{
    private static function isStockAffecting(string $docType, array $operation = []): bool
    {
        $handleStockWithInOut = filter_var(
            env('HANDLE_STOCK_WITH_IN_OUT', false),
            FILTER_VALIDATE_BOOL
        );


        // 🔁 switch logic
        if ($handleStockWithInOut) {
            return in_array($docType, [
                'transfernote',
                'receiptnote',
                'deliverynote',
                'adjustmentnote',
            ]);
        }

        // 🔒 default behavior
        return in_array($docType, [
            'transfernote',
            'exitnote',
            'entrynote',
            'adjustmentnote',
        ]);
    }

    private static function getEffectiveConfirmedStatus(Operation $operation): string
    {
        $handleStockWithInOut = filter_var(
            env('HANDLE_STOCK_WITH_IN_OUT', false),
            FILTER_VALIDATE_BOOL
        );

        if ($handleStockWithInOut) {
            return match ($operation->docType) {
                'receiptnote'  => 'received',
                'deliverynote' => 'delivered',
                default        => 'confirmed',
            };
        }

        return 'confirmed';
    }


    public static function handleStatusChange(Operation $operation, $oldStatus, $newStatus)
    {
            Log::info('HANDLE STATUS TRIGGERED', [
                'operationId' => $operation->id,
                'oldStatus' => $oldStatus,
                'newStatus' => $newStatus,
                'docType' => $operation->docType,
            ]);

        if (!self::isStockAffecting($operation->docType, $operation->toArray())) {
              Log::info('NOT STOCK AFFECTING', [
                'docType' => $operation->docType,
            ]);
            return;
        }

        if ($oldStatus === $newStatus) {
            return;
        }

        $confirmedStatus = self::getEffectiveConfirmedStatus($operation);
        // ⬆️ ENTER confirmed / received / delivered
        if ($newStatus === $confirmedStatus && $oldStatus !== $confirmedStatus) {
            self::registerStock($operation);
            return;
        }

        // ⬇️ LEAVE confirmed / received / delivered
        if ($oldStatus === $confirmedStatus && $newStatus !== $confirmedStatus) {
            self::deleteStockLogs($operation);
            return;
        }

        Log::info('DEBUG STOCK', [
            'docType' => $operation->docType,
            'handleStockWithInOut' => env('HANDLE_STOCK_WITH_IN_OUT'),
            'expectedConfirmedStatus' => self::getEffectiveConfirmedStatus($operation),
            'newStatus' => $newStatus
        ]);
    }


    private static function registerStock(Operation $operation)
    {
        $zid = uniqid('stock_', true);

        if (empty($operation->items)) {
            return;
        }

        $batch = strtoupper(substr(Str::uuid()->toString(), 0, 8));

        foreach ($operation->items as $index => $item) {
            try {

                if (!empty($item['isSeparator'])) {
                    continue;
                }

                if (empty($item['item'])) {
                    continue;
                }

                $product = $item['item'];
                $objectId = $product['id'] ?? null;

                if (!$objectId) {
                    continue;
                }

                // Dispatch stock log
                SetStockLog::dispatchSync([
                    'productId' => $objectId,
                    'batch' => $batch,
                    'productName' => $product['name'] ?? null,
                    'productCode' => $product['ref'] ?? null,
                    'operationType' => $operation->docType ?? null,
                    'operationCode' => $operation->docId ?? null,
                    'quantity' => $item['qty'] ?? $product['qty'] ?? null,
                   'unite' => $item['unit']['name'] ?? $product['unit']['name'] ?? null,
                    'price' => $item['price'] ?? null,
                    'operator' => $operation->personInCharge ?? null,
                    'operatorId' => $operation->userId ?? null,
                    'warehouse' => $operation->docType === 'transfernote'
                        ? $operation->toWarehouse?->name
                        : $operation->warehouse?->name,
                    'warehouseId' => $operation->warehouseId ?? null,
                ]);
                $handleStockWithInOut = filter_var(
                    env('HANDLE_STOCK_WITH_IN_OUT', false),
                    FILTER_VALIDATE_BOOL
                );
                if ($handleStockWithInOut) {
                    $qty = $item['qty'] ?? 0;
                    $costPrice = $operation->docType === 'receiptnote' ? ($item['price'] ?? 0) : ($product['costPrice'] ?? 0);
                    $salePrice = $operation->docType === 'deliverynote' ? ($item['price'] ?? 0) : ($product['salePrice'] ?? 0);
                } else {
                    $qty = $item['qty'] ?? 0;
                    $salePrice = $operation->docType === 'exitnote' ? ($item['price'] ?? 0) : ($product['salePrice'] ?? 0);
                    $costPrice = $operation->docType === 'entrynote' ? ($item['price'] ?? 0) : ($product['costPrice'] ?? 0);
                }
                // Apply stock snapshot

                StockSnapshotService::apply($objectId, $operation->docType, $qty, $salePrice, $costPrice);

                // Create immobilisation if needed
                if (!empty($product['type']['value']) && $product['type']['value'] === 'immobilisation') {
                    Immobilisation::create([
                        'productId' => $objectId,
                        'acquisitionDate' => $operation->date,
                        'acquisitionQty' => $qty,
                        'acquisitionValue' => $item['price'] ?? 0,
                        'amortisationYears' => $product['amortisationYears'] ?? 0,
                        'amortisationRate' => $product['amortisationRate'] ?? 0,
                        'annualAmortisation' => $product['annualAmortisation'] ?? 0,
                        'accumulatedAmortisation' => 0,
                        'netBookValue' => $item['price'] ?? 0,
                        'status' => 'active',
                    ]);
                }

                $updatePrice = filter_var(
                    env('UPDATE_PRICE_AFTER_OPERATION', false),
                    FILTER_VALIDATE_BOOL
                );
                Log::info($updatePrice.'***'.$product['ref'].'***salePrice :'. $salePrice.'/***cost :'. $costPrice);
                if (!empty($product['ref']) && $updatePrice) {
                    Log::info($updatePrice.'***'.$product['ref'].'***salePrice :'. $salePrice.'/***cost :'. $costPrice);
                    self::updateProductPricesByRef(
                        $product['ref'],
                        $salePrice,
                        $costPrice
                    );
                }
            } catch (\Throwable $e) {
                Log::error("Error processing item", [
                    'index' => $index,
                    'item' => $item,
                    'operationId' => $operation->id,
                    'message' => $e->getMessage(),
                    'zid' => $zid
                ]);
            }
        }
    }


    private static function deleteStockLogs(Operation $operation)
    {
        $logs = StockLog::where('operationCode', $operation->docId)->get();
        foreach ($logs as $log) {
            StockSnapshotService::rollback(
                $log->productId,
                $log->operationType,
                $log->quantity
            );
        }
        StockLog::where('operationCode', $operation->docId)->delete();
        $operation->update(['isInWarehouse' => false]);
    }

    public static function updateProductPricesByRef(
        string $productRef,
        ?float $salePrice = null,
        ?float $costPrice = null
    ): bool {

        $product = Product::where('ref', $productRef)->first();
        if (!$product) {
            return false;
        }

        $dataToUpdate = [];
        // ✅ CHECK SALE PRICE
        if ($salePrice !== null) {
            if ((float) $product->salePrice !== (float) $salePrice) {
                $dataToUpdate['salePrice'] = $salePrice;
            }
        }
        if ($costPrice !== null) {
            if ((float) $product->costPrice !== (float) $costPrice) {
                $dataToUpdate['costPrice'] = $costPrice;
            }
        }
        if (empty($dataToUpdate)) {
            return false;
        }
        $product->update($dataToUpdate);

        return true;
    }
}
