<?php

declare(strict_types=1);

namespace App\Console\Commands;

use App\Jobs\Alerts\DeliverAlertsJob;
use App\Jobs\Alerts\EvaluateAlertsJob;
use App\Models\Workspace;
use App\Services\OperationRunService;
use Carbon\CarbonImmutable;
use Illuminate\Console\Command;
use Illuminate\Support\Collection;

class TenantpilotDispatchAlerts extends Command
{
    protected $signature = 'tenantpilot:alerts:dispatch {--workspace=* : Limit dispatch to one or more workspace IDs}';

    protected $description = 'Queue workspace-scoped alert evaluation and delivery jobs idempotently.';

    public function handle(OperationRunService $operationRuns): int
    {
        if (! (bool) config('tenantpilot.alerts.enabled', true)) {
            return self::SUCCESS;
        }

        $workspaceFilter = array_values(array_filter(array_map(
            static fn (mixed $value): int => (int) $value,
            (array) $this->option('workspace'),
        )));

        $workspaces = $this->resolveWorkspaces($workspaceFilter);

        $slotKey = CarbonImmutable::now('UTC')->format('YmdHi').'Z';

        $queuedEvaluate = 0;
        $queuedDeliver = 0;
        $skippedEvaluate = 0;
        $skippedDeliver = 0;

        foreach ($workspaces as $workspace) {
            $evaluateRun = $operationRuns->ensureWorkspaceRunWithIdentity(
                workspace: $workspace,
                type: 'alerts.evaluate',
                identityInputs: ['slot_key' => $slotKey],
                context: [
                    'trigger' => 'scheduled_dispatch',
                    'slot_key' => $slotKey,
                ],
                initiator: null,
            );

            if ($evaluateRun->wasRecentlyCreated) {
                EvaluateAlertsJob::dispatch((int) $workspace->getKey(), (int) $evaluateRun->getKey());
                $queuedEvaluate++;
            } else {
                $skippedEvaluate++;
            }

            $deliverRun = $operationRuns->ensureWorkspaceRunWithIdentity(
                workspace: $workspace,
                type: 'alerts.deliver',
                identityInputs: ['slot_key' => $slotKey],
                context: [
                    'trigger' => 'scheduled_dispatch',
                    'slot_key' => $slotKey,
                ],
                initiator: null,
            );

            if ($deliverRun->wasRecentlyCreated) {
                DeliverAlertsJob::dispatch((int) $workspace->getKey(), (int) $deliverRun->getKey());
                $queuedDeliver++;
            } else {
                $skippedDeliver++;
            }
        }

        $this->info(sprintf(
            'Alert dispatch scanned %d workspace(s): evaluate queued=%d skipped=%d, deliver queued=%d skipped=%d.',
            $workspaces->count(),
            $queuedEvaluate,
            $skippedEvaluate,
            $queuedDeliver,
            $skippedDeliver,
        ));

        return self::SUCCESS;
    }

    /**
     * @param  array<int, int>  $workspaceIds
     * @return Collection<int, Workspace>
     */
    private function resolveWorkspaces(array $workspaceIds): Collection
    {
        return Workspace::query()
            ->when(
                $workspaceIds !== [],
                fn ($query) => $query->whereIn('id', $workspaceIds),
                fn ($query) => $query->whereHas('tenants'),
            )
            ->orderBy('id')
            ->get();
    }
}
