<?php

namespace App\Console\Commands;

use App\Jobs\SyncCustomerQualityAudienceJob;
use App\Services\Customer\CustomerQualityService;
use App\Services\Meta\MetaCustomerAudienceSyncService;
use Illuminate\Console\Command;

class CustomerQualityAudienceSyncCommand extends Command
{
    protected $signature = 'customer-quality:sync-audiences
        {--audience=all}
        {--mode=dry_run}
        {--confirm-test : Confirm the one-customer add and cleanup API test}
        {--confirm-live : Confirm the full live Meta audience change}
        {--create-lookalike}
        {--check-status}';

    protected $description = 'Dry-run or live sync customer quality value-based audiences to Meta.';

    public function __construct(
        private readonly MetaCustomerAudienceSyncService $metaAudienceSyncService,
        private readonly CustomerQualityService $customerQualityService
    ) {
        parent::__construct();
    }

    public function handle(): int
    {
        $requestedMode = (string) $this->option('mode');
        $mode = in_array($requestedMode, ['dry_run', 'test_upload', 'live'], true)
            ? $requestedMode
            : 'dry_run';
        $audienceOption = (string) $this->option('audience');
        $audienceKeys = $audienceOption === 'all'
            ? array_keys(CustomerQualityService::AUDIENCE_NAMES)
            : [$audienceOption];

        $failed = 0;

        foreach ($audienceKeys as $audienceKey) {
            if (! array_key_exists($audienceKey, CustomerQualityService::AUDIENCE_NAMES)) {
                $this->error("Unknown customer quality audience: {$audienceKey}");
                $failed++;
                continue;
            }

            try {
                if ($this->option('check-status')) {
                    $status = $this->metaAudienceSyncService->refreshAudienceStatus($audienceKey);
                    $this->info(sprintf(
                        '%s status: %s (operation code: %s).',
                        CustomerQualityService::AUDIENCE_NAMES[$audienceKey],
                        data_get($status, 'state', 'unknown'),
                        data_get($status, 'operation_code', 'n/a')
                    ));
                    continue;
                }

                if ($this->option('create-lookalike') && $audienceKey === CustomerQualityService::HIGH_AUDIENCE_KEY) {
                    $lookalikeId = $this->metaAudienceSyncService->createBangladeshLookalikeAudience($audienceKey);
                    $this->info('Bangladesh 1% Lookalike audience ready: ' . $lookalikeId);
                    continue;
                }

                if ($mode !== 'dry_run') {
                    if ($mode === 'test_upload' && ! $this->option('confirm-test')) {
                        throw new \RuntimeException('Pass --confirm-test after reviewing the matching dry run.');
                    }

                    if ($mode === 'live' && ! $this->option('confirm-live')) {
                        throw new \RuntimeException('Pass --confirm-live after reviewing the accepted test upload.');
                    }

                    if (config('queue.default') === 'sync') {
                        throw new \RuntimeException('Test Upload and Live Meta Sync require an async queue driver.');
                    }

                    $plan = $this->customerQualityService->audiencePlan($audienceKey);
                    $dryRun = $this->customerQualityService->latestValidDryRun(
                        $audienceKey,
                        $plan['scope_hash'],
                        $plan['checksum']
                    );

                    if (! $dryRun) {
                        throw new \RuntimeException('Run a fresh matching dry run before queuing this Meta upload.');
                    }

                    if ($mode === 'live' && ! $this->customerQualityService->hasSuccessfulTestUpload(
                        $audienceKey,
                        $plan['scope_hash'],
                        $plan['checksum']
                    )) {
                        throw new \RuntimeException('An accepted-and-cleaned test upload for this checksum is required before Live Meta Sync.');
                    }

                    SyncCustomerQualityAudienceJob::dispatch($dryRun->id, $audienceKey, null, null, $mode);
                    $this->info(CustomerQualityService::AUDIENCE_NAMES[$audienceKey] . " {$mode} queued.");
                    continue;
                }

                $log = $this->metaAudienceSyncService->sync($audienceKey, 'dry_run');
                $this->info(sprintf(
                    '%s %s completed. Eligible: %d, Add: %d, Remove: %d, Skipped: %d, Checksum: %s, Expires: %s.',
                    CustomerQualityService::AUDIENCE_NAMES[$audienceKey],
                    $mode,
                    $log->eligible_count,
                    $log->add_count,
                    $log->remove_count,
                    $log->skipped_count,
                    $log->checksum ?: 'n/a',
                    $log->expires_at?->toDateTimeString() ?: 'n/a'
                ));

            } catch (\Throwable $throwable) {
                report($throwable);
                $this->error(CustomerQualityService::AUDIENCE_NAMES[$audienceKey] . ' sync failed: ' . $throwable->getMessage());
                $failed++;
            }
        }

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