<?php

declare(strict_types=1);

namespace App\Console\Commands;

use App\Jobs\SyncBackendDataPool;
use Illuminate\Console\Command;

use function Laravel\Prompts\confirm;
use function Laravel\Prompts\info;
use function Laravel\Prompts\spin;
use function Laravel\Prompts\table;
use function Laravel\Prompts\warning;

class SyncBackendDataPoolCommand extends Command
{
    /**
     * The name and signature of the console command.
     */
    protected $signature = 'backend:sync-data-pool
                            {--full : Perform a full sync (truncate and rebuild)}
                            {--incremental : Perform an incremental sync (only new/updated records)}
                            {--batch-size=1000 : Number of records to process per batch}
                            {--queue : Dispatch the job to the queue instead of running synchronously}
                            {--stats : Show statistics only, do not perform sync}';

    /**
     * The console command description.
     */
    protected $description = 'Sync backend.transactions + backend.transaction_outputs to public.backend_data_pool';

    /**
     * Execute the console command.
     */
    public function handle(): int
    {
        // Show stats only
        if ($this->option('stats')) {
            return $this->showStats();
        }

        // Determine sync type
        $fullSync = $this->option('full') ?? ! $this->option('incremental');

        if ($fullSync) {
            info('Preparing for FULL SYNC');
            warning('This will truncate and rebuild the entire backend_data_pool table.');

            if (! $this->option('no-interaction') && ! confirm('Do you want to continue?', true)) {
                info('Sync cancelled.');

                return self::SUCCESS;
            }
        } else {
            info('Preparing for INCREMENTAL SYNC');
        }

        $batchSize = (int) $this->option('batch-size');

        // Show current stats before sync
        $this->showStatsBefore();

        // Create the job
        $job = new SyncBackendDataPool(
            fullSync: $fullSync,
            batchSize: $batchSize
        );

        // Execute the job
        if ($this->option('queue')) {
            info('Dispatching job to queue...');
            dispatch($job);
            info('Job dispatched successfully!');
        } else {
            info('Running sync synchronously...');

            spin(
                fn () => $job->handle(),
                'Syncing data...'
            );

            info('Sync completed successfully!');
        }

        // Show stats after sync
        $this->showStatsAfter();

        return self::SUCCESS;
    }

    /**
     * Show statistics only
     */
    private function showStats(): int
    {
        $job = new SyncBackendDataPool;
        $stats = $job->getStats();

        info('Backend Data Pool Statistics');

        table(
            ['Metric', 'Value'],
            [
                ['Backend Transactions (done)', number_format($stats['backend_transactions_done'])],
                ['Backend Transaction Outputs', number_format($stats['backend_transaction_outputs'])],
                ['Data Pool Records', number_format($stats['backend_data_pool_records'])],
                ['Last Synced At', $stats['last_synced_at'] ?? 'Never'],
            ]
        );

        return self::SUCCESS;
    }

    /**
     * Show stats before sync
     */
    private function showStatsBefore(): void
    {
        $job = new SyncBackendDataPool;
        $stats = $job->getStats();

        $this->newLine();
        info('Stats BEFORE sync:');
        table(
            ['Metric', 'Value'],
            [
                ['Backend Transactions (done)', number_format($stats['backend_transactions_done'])],
                ['Data Pool Records', number_format($stats['backend_data_pool_records'])],
                ['Last Synced At', $stats['last_synced_at'] ?? 'Never'],
            ]
        );
        $this->newLine();
    }

    /**
     * Show stats after sync
     */
    private function showStatsAfter(): void
    {
        $job = new SyncBackendDataPool;
        $stats = $job->getStats();

        $this->newLine();
        info('Stats AFTER sync:');
        table(
            ['Metric', 'Value'],
            [
                ['Backend Transactions (done)', number_format($stats['backend_transactions_done'])],
                ['Data Pool Records', number_format($stats['backend_data_pool_records'])],
                ['Last Synced At', $stats['last_synced_at']],
            ]
        );
        $this->newLine();
    }
}
