<?php

namespace App\Console\Commands;

use App\Models\Order;
use App\Services\Shipment\ShipmentStatusSyncService;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Log;

class BackfillOrderStatusFromShipments extends Command
{
    protected $signature = 'orders:backfill-status-from-shipments
                            {--dry-run : Report changes without updating orders}
                            {--order-id= : Limit to a single order ID}
                            {--chunk=100 : Number of orders to process per chunk}';

    protected $description = 'Backfill orders.status from existing shipments.status using the centralized mapper (DB-only, no courier API calls). Production: (1) php artisan migrate, (2) --dry-run, (3) run without --dry-run, (4) verify admin orders and laravel.log.';

    public function __construct(
        private readonly ShipmentStatusSyncService $statusSyncService
    ) {
        parent::__construct();
    }

    public function handle(): int
    {
        $dryRun = (bool) $this->option('dry-run');
        $orderId = $this->option('order-id');
        $chunkSize = max(1, (int) $this->option('chunk'));

        $counters = [
            'scanned' => 0,
            'updated' => 0,
            'unchanged' => 0,
            'skipped_no_mappable' => 0,
        ];

        if ($dryRun) {
            $this->warn('Dry-run mode: no orders will be updated.');
        }

        $query = Order::query()
            ->whereHas('shipments')
            ->with('shipments');

        if ($orderId !== null && $orderId !== '') {
            $query->whereKey((int) $orderId);
        }

        $query->chunkById($chunkSize, function ($orders) use ($dryRun, &$counters): void {
            foreach ($orders as $order) {
                $counters['scanned']++;

                $resolution = $this->statusSyncService->resolveOrderStatusFromShipments($order);

                if ($resolution === null) {
                    $counters['skipped_no_mappable']++;
                    continue;
                }

                if (!$resolution['would_change']) {
                    $counters['unchanged']++;
                    continue;
                }

                if ($dryRun) {
                    $this->line(sprintf(
                        'Order #%d: %s → %s (derived: %s)',
                        $order->id,
                        $order->status,
                        $resolution['next'],
                        $resolution['derived']
                    ));
                    $counters['updated']++;
                    continue;
                }

                $oldStatus = $order->status;
                $changed = $this->statusSyncService->syncOrderFromShipments($order);

                if ($changed) {
                    $counters['updated']++;
                    Log::info('Order status backfilled from shipments', [
                        'order_id' => $order->id,
                        'from_status' => $oldStatus,
                        'to_status' => $order->fresh()->status,
                    ]);
                } else {
                    $counters['unchanged']++;
                }
            }
        });

        $this->newLine();
        $this->info(sprintf(
            'Backfill complete. scanned=%d updated=%d unchanged=%d skipped_no_mappable=%d%s',
            $counters['scanned'],
            $counters['updated'],
            $counters['unchanged'],
            $counters['skipped_no_mappable'],
            $dryRun ? ' (dry-run)' : ''
        ));

        return Command::SUCCESS;
    }
}
