<?php

namespace App\Console\Commands;

use App\Models\Warehouse\DivisionDelivery;
use App\Models\Warehouse\IncomingOperation;
use App\Models\Warehouse\IncomingOperationItem;
use App\Models\Warehouse\Inventory;
use Illuminate\Console\Command;

class SyncDivisionDeliveryTotals extends Command
{
    protected $signature = 'sync:division-delivery-totals
                            {--dry-run : Show what would be updated without making changes}
                            {--division= : Only sync specific division ID}
                            {--item= : Only sync specific item ID}';

    protected $description = 'Recalculate and sync DivisionDelivery totals from actual supplier delivery operations';

    public function handle()
    {
        $isDryRun = $this->option('dry-run');
        $divisionFilter = $this->option('division');
        $itemFilter = $this->option('item');

        if ($isDryRun) {
            $this->info('DRY RUN MODE - No changes will be made');
        }

        $this->info('Syncing DivisionDelivery totals from supplier delivery operations...');
        $this->newLine();

        // Get all supplier deliveries grouped by division and item
        $query = IncomingOperation::where('operation_type', 'supplier_delivery')
            ->where('status', 'completed')
            ->whereNotNull('division_id')
            ->with(['items.item', 'projectDivision']);

        if ($divisionFilter) {
            $query->where('division_id', $divisionFilter);
        }

        $operations = $query->get();

        // Build expected totals by division_id and item_id
        $expectedTotals = [];

        foreach ($operations as $operation) {
            $divisionId = $operation->division_id;
            $divisionName = $operation->projectDivision->division_name ?? 'Unknown';

            foreach ($operation->items as $item) {
                if ($itemFilter && $item->item_id != $itemFilter) {
                    continue;
                }

                $key = "{$divisionId}_{$item->item_id}";
                $qty = $item->quantity_delivered ?? 0;
                $unitPrice = $item->unit_price_aed ?? $item->unit_price ?? 0;
                $value = $qty * $unitPrice;

                if (!isset($expectedTotals[$key])) {
                    $expectedTotals[$key] = [
                        'division_id' => $divisionId,
                        'division_name' => $divisionName,
                        'item_id' => $item->item_id,
                        'item_code' => $item->item->item_code ?? 'N/A',
                        'total_quantity_delivered' => 0,
                        'total_quantity_issued' => 0, // Items that go directly to project (project_site + foc)
                        'total_value' => 0,
                        'first_delivery_date' => $operation->operation_date,
                        'last_delivery_date' => $operation->operation_date,
                    ];
                }

                $expectedTotals[$key]['total_quantity_delivered'] += $qty;
                $expectedTotals[$key]['total_value'] += $value;

                // Items delivered to project_site or foc are considered "issued"
                if (in_array($operation->delivery_type, ['project_site', 'foc'])) {
                    $expectedTotals[$key]['total_quantity_issued'] += $qty;
                }

                // Track delivery dates
                if ($operation->operation_date < $expectedTotals[$key]['first_delivery_date']) {
                    $expectedTotals[$key]['first_delivery_date'] = $operation->operation_date;
                }
                if ($operation->operation_date > $expectedTotals[$key]['last_delivery_date']) {
                    $expectedTotals[$key]['last_delivery_date'] = $operation->operation_date;
                }
            }
        }

        $synced = 0;
        $created = 0;
        $skipped = 0;

        foreach ($expectedTotals as $key => $expected) {
            // Get actual inventory for this division/item
            $actualInventory = Inventory::where('division_id', $expected['division_id'])
                ->where('item_id', $expected['item_id'])
                ->sum('quantity_available');

            // Get current DivisionDelivery record
            $current = DivisionDelivery::where('division_id', $expected['division_id'])
                ->where('item_id', $expected['item_id'])
                ->first();

            $itemCode = $expected['item_code'];
            $divisionName = $expected['division_name'];

            if ($current) {
                // Check for mismatches
                $mismatches = [];

                if (abs($current->total_quantity_delivered - $expected['total_quantity_delivered']) > 0.01) {
                    $mismatches[] = "delivered: {$current->total_quantity_delivered} -> {$expected['total_quantity_delivered']}";
                }
                if (abs($current->total_quantity_issued - $expected['total_quantity_issued']) > 0.01) {
                    $mismatches[] = "issued: {$current->total_quantity_issued} -> {$expected['total_quantity_issued']}";
                }
                if (abs($current->current_available_quantity - $actualInventory) > 0.01) {
                    $mismatches[] = "available: {$current->current_available_quantity} -> {$actualInventory}";
                }
                if (abs($current->total_value - $expected['total_value']) > 0.01) {
                    $mismatches[] = "value: {$current->total_value} -> {$expected['total_value']}";
                }

                if (!empty($mismatches)) {
                    $this->line("Updating: {$itemCode} | {$divisionName}");
                    foreach ($mismatches as $m) {
                        $this->line("  - {$m}");
                    }

                    if (!$isDryRun) {
                        $current->total_quantity_delivered = $expected['total_quantity_delivered'];
                        $current->total_quantity_issued = $expected['total_quantity_issued'];
                        $current->current_available_quantity = $actualInventory;
                        $current->total_value = $expected['total_value'];
                        $current->average_unit_price = $expected['total_quantity_delivered'] > 0
                            ? $expected['total_value'] / $expected['total_quantity_delivered']
                            : 0;
                        $current->first_delivery_date = $expected['first_delivery_date'];
                        $current->last_delivery_date = $expected['last_delivery_date'];
                        $current->last_updated = now();
                        $current->save();
                    }

                    $synced++;
                } else {
                    $skipped++;
                }
            } else {
                // Create new record
                $this->line("Creating: {$itemCode} | {$divisionName}");
                $this->line("  delivered: {$expected['total_quantity_delivered']}, issued: {$expected['total_quantity_issued']}, value: {$expected['total_value']}");

                if (!$isDryRun) {
                    DivisionDelivery::create([
                        'division_id' => $expected['division_id'],
                        'item_id' => $expected['item_id'],
                        'total_quantity_delivered' => $expected['total_quantity_delivered'],
                        'current_available_quantity' => $actualInventory,
                        'total_quantity_issued' => $expected['total_quantity_issued'],
                        'average_unit_price' => $expected['total_quantity_delivered'] > 0
                            ? $expected['total_value'] / $expected['total_quantity_delivered']
                            : 0,
                        'total_value' => $expected['total_value'],
                        'first_delivery_date' => $expected['first_delivery_date'],
                        'last_delivery_date' => $expected['last_delivery_date'],
                        'last_updated' => now()
                    ]);
                }

                $created++;
            }
        }

        $this->newLine();
        $this->info("=== Summary ===");
        $this->info("Records processed: " . count($expectedTotals));
        $this->info("Already in sync: {$skipped}");

        if ($isDryRun) {
            $this->info("Would be updated: {$synced}");
            $this->info("Would be created: {$created}");
        } else {
            $this->info("Updated: {$synced}");
            $this->info("Created: {$created}");
        }

        if ($isDryRun && ($synced > 0 || $created > 0)) {
            $this->newLine();
            $this->warn("Run without --dry-run to apply the sync");
        }

        return 0;
    }
}
