<?php

declare(strict_types=1);

namespace App\Console\Commands;

use App\Models\Tenant;
use App\Services\Runbooks\FindingsLifecycleBackfillRunbookService;
use App\Services\Runbooks\FindingsLifecycleBackfillScope;
use Illuminate\Console\Command;
use Illuminate\Validation\ValidationException;

class TenantpilotBackfillFindingLifecycle extends Command
{
    protected $signature = 'tenantpilot:findings:backfill-lifecycle
        {--tenant=* : Limit to tenant_id/external_id}';

    protected $description = 'Queue tenant-scoped findings lifecycle backfill jobs idempotently.';

    public function handle(FindingsLifecycleBackfillRunbookService $runbookService): int
    {
        $tenantIdentifiers = array_values(array_filter((array) $this->option('tenant')));

        if ($tenantIdentifiers === []) {
            $this->error('Provide one or more tenants via --tenant={id|external_id}.');

            return self::FAILURE;
        }

        $tenants = $this->resolveTenants($tenantIdentifiers);

        if ($tenants->isEmpty()) {
            $this->info('No tenants matched the provided identifiers.');

            return self::SUCCESS;
        }

        $queued = 0;
        $skipped = 0;
        $nothingToDo = 0;

        foreach ($tenants as $tenant) {
            if (! $tenant instanceof Tenant) {
                continue;
            }

            try {
                $run = $runbookService->start(
                    scope: FindingsLifecycleBackfillScope::singleTenant((int) $tenant->getKey()),
                    initiator: null,
                    reason: null,
                    source: 'cli',
                );
            } catch (ValidationException $e) {
                $errors = $e->errors();

                if (isset($errors['preflight.affected_count'])) {
                    $nothingToDo++;

                    continue;
                }

                $this->error(sprintf(
                    'Backfill blocked for tenant %d: %s',
                    (int) $tenant->getKey(),
                    $e->getMessage(),
                ));

                return self::FAILURE;
            }

            if (! $run->wasRecentlyCreated) {
                $skipped++;

                continue;
            }

            $queued++;
        }

        $this->info(sprintf(
            'Queued %d backfill run(s), skipped %d duplicate run(s), nothing to do %d.',
            $queued,
            $skipped,
            $nothingToDo,
        ));

        return self::SUCCESS;
    }

    /**
     * @param  array<int, string>  $tenantIdentifiers
     * @return \Illuminate\Support\Collection<int, Tenant>
     */
    private function resolveTenants(array $tenantIdentifiers)
    {
        $tenantIds = [];

        foreach ($tenantIdentifiers as $identifier) {
            $tenant = Tenant::query()
                ->forTenant($identifier)
                ->first();

            if ($tenant instanceof Tenant) {
                $tenantIds[] = (int) $tenant->getKey();
            }
        }

        $tenantIds = array_values(array_unique($tenantIds));

        if ($tenantIds === []) {
            return collect();
        }

        return Tenant::query()
            ->whereIn('id', $tenantIds)
            ->orderBy('id')
            ->get();
    }
}
