<?php

namespace App\Console\Commands;

use App\Models\Sale;
use App\Support\SaleFulfillment;
use App\Support\SaleType;
use Illuminate\Console\Command;

class SyncExchangeReplacementsCommand extends Command
{
    protected $signature = 'sales:sync-exchange-replacements
                            {--original= : Original sale number to limit the sync}
                            {--dry-run : Show how many packs would be added without saving}';

    protected $description = 'Add exchange replacement packs onto the original sale bill when they were recorded only on the exchange';

    public function handle(): int
    {
        $dryRun = (bool) $this->option('dry-run');
        $originalNumber = $this->option('original');

        $query = Sale::query()
            ->where('type', SaleType::EXCHANGE)
            ->whereNotNull('related_sale_id')
            ->orderBy('id');

        if (is_string($originalNumber) && $originalNumber !== '') {
            $originalSaleId = Sale::query()
                ->where('type', SaleType::SALE)
                ->where('sale_number', $originalNumber)
                ->value('id');

            if ($originalSaleId === null) {
                $this->error("Original sale not found: {$originalNumber}");

                return self::FAILURE;
            }

            $query->where('related_sale_id', $originalSaleId);
        }

        $exchangeSales = $query->get();

        if ($exchangeSales->isEmpty()) {
            $this->info('No exchanges found to sync.');

            return self::SUCCESS;
        }

        $totalAdded = 0;
        $synced = 0;

        foreach ($exchangeSales as $exchangeSale) {
            if (SaleFulfillment::exchangeReplacementsSynced($exchangeSale)) {
                continue;
            }

            $added = SaleFulfillment::syncExchangeReplacementsToOriginalSale($exchangeSale, $dryRun);

            if ($added === 0) {
                continue;
            }

            $exchangeSale->loadMissing('relatedSale');
            $originalNumberLabel = $exchangeSale->relatedSale?->sale_number ?? (string) $exchangeSale->related_sale_id;

            $this->line(sprintf(
                '%s exchange %s → original %s: %d pack(s)%s',
                $dryRun ? '[dry-run]' : 'Synced',
                $exchangeSale->sale_number,
                $originalNumberLabel,
                $added,
                $dryRun ? ' would be added' : ' added',
            ));

            $totalAdded += $added;
            $synced++;
        }

        if ($synced === 0) {
            $this->info('All exchanges are already synced onto their original sales.');

            return self::SUCCESS;
        }

        $this->info(sprintf(
            '%s %d exchange(s), %d pack(s) total.',
            $dryRun ? 'Would update' : 'Updated',
            $synced,
            $totalAdded,
        ));

        return self::SUCCESS;
    }
}
