<?php

namespace App\Console\Commands;

use App\Exceptions\CourierException;
use App\Models\Order;
use App\Models\OrderCourierShipment;
use App\Services\Courier\CourierTrackingService;
use Illuminate\Console\Command;

class CourierStatusSyncCommand extends Command
{
    protected $signature = 'courier:sync-statuses {--order_id=} {--limit=50}';

    protected $description = 'Sync booked courier shipments and update internal order statuses safely.';

    public function __construct(
        private readonly CourierTrackingService $courierTrackingService
    ) {
        parent::__construct();
    }

    public function handle(): int
    {
        $query = OrderCourierShipment::query()
            ->with('order')
            ->where('booking_status', 'booked')
            ->whereHas('order', function ($query) {
                $query->whereNotIn('order_status', ['delivered', 'returned', 'canceled', 'failed']);
            })
            ->orderBy('courier_synced_at')
            ->orderBy('id');

        if ($orderId = $this->option('order_id')) {
            $query->where('order_id', (int) $orderId);
        } else {
            $query->limit(max((int) $this->option('limit'), 1));
        }

        $shipments = $query->get();

        if ($shipments->isEmpty()) {
            $this->info('No eligible courier shipments found for sync.');
            return self::SUCCESS;
        }

        $synced = 0;
        $failed = 0;

        foreach ($shipments as $shipment) {
            $order = $shipment->order;

            if (! $order instanceof Order) {
                continue;
            }

            try {
                $this->courierTrackingService->sync($order);
                $synced++;
                $this->line("Synced order #{$order->id} successfully.");
            } catch (CourierException $exception) {
                $failed++;
                $this->warn("Order #{$order->id} sync skipped/failed: {$exception->getMessage()}");
            } catch (\Throwable $throwable) {
                $failed++;
                report($throwable);
                $this->error("Order #{$order->id} sync failed unexpectedly: {$throwable->getMessage()}");
            }
        }

        $this->info("Courier sync completed. Success: {$synced}, Failed: {$failed}.");

        return $failed > 0 ? self::FAILURE : self::SUCCESS;
    }
}
