<?php

declare(strict_types=1);

namespace App\Jobs;

use App\Models\OperationRun;
use App\Services\OperationRunService;
use App\Services\Runbooks\FindingsLifecycleBackfillRunbookService;
use App\Services\System\AllowedTenantUniverse;
use App\Support\OperationRunOutcome;
use App\Support\OperationRunStatus;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;

class BackfillFindingLifecycleWorkspaceJob implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    public function __construct(
        public readonly int $operationRunId,
        public readonly int $workspaceId,
    ) {}

    public function handle(
        OperationRunService $operationRunService,
        AllowedTenantUniverse $allowedTenantUniverse,
        FindingsLifecycleBackfillRunbookService $runbookService,
    ): void {
        $run = OperationRun::query()->find($this->operationRunId);

        if (! $run instanceof OperationRun) {
            return;
        }

        if ((int) $run->workspace_id !== $this->workspaceId) {
            return;
        }

        if ($run->tenant_id !== null) {
            return;
        }

        $tenantIds = $allowedTenantUniverse
            ->query()
            ->where('workspace_id', $this->workspaceId)
            ->orderBy('id')
            ->pluck('id')
            ->map(static fn (mixed $id): int => (int) $id)
            ->all();

        $tenantCount = count($tenantIds);

        $operationRunService->updateRun(
            $run,
            status: OperationRunStatus::Running->value,
            outcome: OperationRunOutcome::Pending->value,
            summaryCounts: [
                'tenants' => $tenantCount,
                'total' => $tenantCount,
                'processed' => 0,
                'updated' => 0,
                'skipped' => 0,
                'failed' => 0,
            ],
        );

        if ($tenantCount === 0) {
            $operationRunService->updateRun(
                $run,
                status: OperationRunStatus::Completed->value,
                outcome: OperationRunOutcome::Succeeded->value,
            );

            $runbookService->maybeFinalize($run);

            return;
        }

        foreach ($tenantIds as $tenantId) {
            if ($tenantId <= 0) {
                continue;
            }

            BackfillFindingLifecycleTenantIntoWorkspaceRunJob::dispatch(
                operationRunId: (int) $run->getKey(),
                workspaceId: $this->workspaceId,
                tenantId: $tenantId,
            );
        }
    }
}
