/**
 * Start Feature Use Case
 *
 * Transitions a Pending feature to its active lifecycle and spawns
 * the agent. Validates lifecycle state, checks parent dependency
 * gates, and reuses the existing AgentRun record.
 */
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
    if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var __param = (this && this.__param) || function (paramIndex, decorator) {
    return function (target, key) { decorator(target, key, paramIndex); }
};
import { injectable, inject } from 'tsyringe';
import { SdlcLifecycle } from '../../../domain/generated/output.js';
import { POST_IMPLEMENTATION } from '../../../domain/lifecycle-gates.js';
let StartFeatureUseCase = class StartFeatureUseCase {
    featureRepo;
    runRepo;
    processService;
    worktreeService;
    constructor(featureRepo, runRepo, processService, worktreeService) {
        this.featureRepo = featureRepo;
        this.runRepo = runRepo;
        this.processService = processService;
        this.worktreeService = worktreeService;
    }
    async execute(featureId) {
        // Resolve feature by exact ID or prefix
        const feature = (await this.featureRepo.findById(featureId)) ??
            (await this.featureRepo.findByIdPrefix(featureId));
        if (!feature) {
            throw new Error(`Feature not found: ${featureId}`);
        }
        // Validate lifecycle is Pending
        if (feature.lifecycle !== SdlcLifecycle.Pending) {
            throw new Error(`Feature "${feature.name}" is not in Pending state (current: ${feature.lifecycle}). Only pending features can be started.`);
        }
        // Validate agentRunId exists
        if (!feature.agentRunId) {
            throw new Error(`No agent run found for feature "${feature.name}"`);
        }
        const agentRun = await this.runRepo.findById(feature.agentRunId);
        if (!agentRun) {
            throw new Error(`No agent run found for feature "${feature.name}"`);
        }
        // Wait for specPath — the web UI creates features in two phases: a fast
        // DB record (specPath: '') followed by background initialization that
        // populates specPath. If the user clicks "Start" before Phase 2 finishes,
        // specPath will still be empty. Poll the DB briefly to let it complete.
        let resolved = feature;
        if (!resolved.specPath) {
            const MAX_POLLS = 20;
            const POLL_INTERVAL_MS = 500;
            for (let i = 0; i < MAX_POLLS; i++) {
                await new Promise((r) => setTimeout(r, POLL_INTERVAL_MS));
                const refreshed = await this.featureRepo.findById(resolved.id);
                if (refreshed?.specPath) {
                    resolved = refreshed;
                    break;
                }
            }
            if (!resolved.specPath) {
                throw new Error(`Feature "${resolved.name}" is still being initialized — please try again shortly`);
            }
        }
        // Check parent gate if feature has a parent
        let targetLifecycle = resolved.fast ? SdlcLifecycle.Implementation : SdlcLifecycle.Requirements;
        let shouldSpawn = true;
        if (resolved.parentId) {
            const parent = await this.featureRepo.findById(resolved.parentId);
            if (!parent ||
                parent.lifecycle === SdlcLifecycle.Blocked ||
                !POST_IMPLEMENTATION.has(parent.lifecycle)) {
                targetLifecycle = SdlcLifecycle.Blocked;
                shouldSpawn = false;
            }
        }
        // Transition lifecycle
        const updatedFeature = {
            ...resolved,
            lifecycle: targetLifecycle,
            updatedAt: new Date(),
        };
        await this.featureRepo.update(updatedFeature);
        // Spawn agent if not blocked
        if (shouldSpawn) {
            const worktreePath = this.worktreeService.getWorktreePath(resolved.repositoryPath, resolved.branch);
            this.processService.spawn(resolved.id, resolved.agentRunId, resolved.repositoryPath, resolved.specPath, worktreePath, {
                approvalGates: resolved.approvalGates,
                threadId: agentRun.threadId,
                push: resolved.push,
                openPr: resolved.openPr,
                forkAndPr: resolved.forkAndPr,
                commitSpecs: resolved.commitSpecs,
                ciWatchEnabled: resolved.ciWatchEnabled,
                enableEvidence: resolved.enableEvidence,
                commitEvidence: resolved.commitEvidence,
                agentType: agentRun.agentType,
                ...(resolved.fast ? { fast: true } : {}),
                ...(agentRun.modelId ? { model: agentRun.modelId } : {}),
            });
        }
        return { feature: updatedFeature, agentRun };
    }
};
StartFeatureUseCase = __decorate([
    injectable(),
    __param(0, inject('IFeatureRepository')),
    __param(1, inject('IAgentRunRepository')),
    __param(2, inject('IFeatureAgentProcessService')),
    __param(3, inject('IWorktreeService')),
    __metadata("design:paramtypes", [Object, Object, Object, Object])
], StartFeatureUseCase);
export { StartFeatureUseCase };
