/**
 * EvaluateSupervisorDecisionUseCase
 *
 * Single entry point used by the supervisor worker (and any other caller
 * that needs an evaluation) to:
 *
 *   1. Short-circuit when the `collaboration` feature flag is off
 *      (NFR-14 byte-identical default behaviour).
 *   2. Resolve the effective {@link SupervisorPolicy} for the event's
 *      scope via {@link GetSupervisorPolicyUseCase} (feature-then-scope
 *      fallback). When no policy exists the caller is told nothing was
 *      done.
 *   3. Call {@link ISupervisorAgent.evaluate} for the LLM (or stub)
 *      verdict.
 *   4. Persist the immutable {@link SupervisorDecision} via
 *      {@link ISupervisorDecisionRepository}.
 *   5. Mirror the decision into `activity_log` with `actor_id =
 *      supervisor:<supervisorRunId>` for audit reproducibility (research
 *      decision 8).
 *
 * Persistence is centralised here so the LangGraph adapter and the
 * in-memory adapter remain pure evaluators (no side effects).
 */
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 { inject, injectable } from 'tsyringe';
import { randomUUID } from 'node:crypto';
import { NotificationEventType, NotificationSeverity, SupervisorVerdict, } from '../../../domain/generated/output.js';
import { GetSupervisorPolicyUseCase } from './get-supervisor-policy.use-case.js';
import { EscalateToUserUseCase } from './escalate-to-user.use-case.js';
let EvaluateSupervisorDecisionUseCase = class EvaluateSupervisorDecisionUseCase {
    supervisorAgent;
    decisionRepository;
    activityLog;
    settings;
    getPolicy;
    escalateToUser;
    constructor(supervisorAgent, decisionRepository, activityLog, settings, getPolicy, escalateToUser) {
        this.supervisorAgent = supervisorAgent;
        this.decisionRepository = decisionRepository;
        this.activityLog = activityLog;
        this.settings = settings;
        this.getPolicy = getPolicy;
        this.escalateToUser = escalateToUser;
    }
    async execute(input) {
        if (!(await this.isCollaborationEnabled())) {
            return { evaluated: false, skippedReason: 'flag-off' };
        }
        const { event, supervisorRunId } = input;
        const policy = await this.getPolicy.execute({
            scopeType: event.scopeType,
            scopeId: event.scopeId,
            featureId: event.featureId,
        });
        if (!policy) {
            return { evaluated: false, skippedReason: 'no-policy' };
        }
        const now = new Date();
        let result;
        try {
            result = await this.supervisorAgent.evaluate({ event, policy });
        }
        catch (err) {
            // FR-22: a supervisor evaluator failure (timeout, model error,
            // exception) MUST NOT crash the caller. Fall back to the standard
            // human approval path by surfacing a SupervisorFailed notification
            // and recording an audit-log entry. No SupervisorDecision row is
            // written because there is no verdict to record.
            const failureReason = err instanceof Error ? err.message : String(err);
            await this.escalateToUser.execute({
                eventType: NotificationEventType.SupervisorFailed,
                severity: NotificationSeverity.Error,
                message: `Supervisor evaluation failed: ${failureReason}`,
                agentRunId: this.resolveAgentRunId(event),
                featureId: event.featureId ?? '',
                featureName: event.featureId ?? '',
                sourceEventId: event.sourceEventId,
                actorId: `supervisor:${supervisorRunId}`,
                auditField: `supervisor.failed.${event.kind}`,
                timestamp: now,
            });
            return { evaluated: false, skippedReason: 'supervisor-failed', failureReason };
        }
        const decision = {
            id: randomUUID(),
            scopeType: event.scopeType,
            scopeId: event.scopeId,
            featureId: event.featureId,
            supervisorRunId,
            sourceEventKind: event.kind,
            sourceEventId: event.sourceEventId,
            verdict: result.verdict,
            rationale: result.rationale,
            modelId: result.modelId,
            promptVersion: result.promptVersion,
            ruleRef: result.ruleRef,
            confidence: result.confidence,
            createdAt: now,
            updatedAt: now,
        };
        await this.decisionRepository.create(decision);
        await this.mirrorToActivityLog(decision, policy, now);
        if (result.verdict === SupervisorVerdict.escalate) {
            // The supervisor punted back to the user — surface that via the
            // notification surface so the user can pick up the gate / question
            // promptly (research decision 9).
            await this.escalateToUser.execute({
                eventType: NotificationEventType.SupervisorEscalated,
                severity: NotificationSeverity.Warning,
                message: result.rationale,
                agentRunId: this.resolveAgentRunId(event),
                featureId: event.featureId ?? '',
                featureName: event.featureId ?? '',
                sourceEventId: event.sourceEventId,
                actorId: `supervisor:${supervisorRunId}`,
                auditField: `supervisor.escalated.${event.kind}`,
                timestamp: now,
            });
        }
        return { evaluated: true, decision };
    }
    resolveAgentRunId(event) {
        if ('agentRunId' in event && typeof event.agentRunId === 'string') {
            return event.agentRunId;
        }
        return '';
    }
    /**
     * Append a single audit row describing the decision. The mirror lives
     * here (rather than in the repository) so the activity-log shape is
     * not coupled to supervisor concerns and so a future audit-target
     * (PmAuditLog, structured logger, etc.) can be swapped in via DI.
     */
    async mirrorToActivityLog(decision, policy, timestamp) {
        const entry = {
            id: randomUUID(),
            // The source event id — gate id, question id, message id — is the
            // closest analogue to a "work item" in the supervisor flow. We
            // intentionally reuse this field so the audit drawer can list every
            // decision attached to the same source event.
            workItemId: decision.sourceEventId,
            fieldName: `supervisor.${decision.sourceEventKind}`,
            oldValue: undefined,
            newValue: decision.verdict,
            actorId: `supervisor:${decision.supervisorRunId}`,
            createdAt: timestamp,
            updatedAt: timestamp,
        };
        await this.activityLog.create(entry);
        // Touch policy so static type-checkers know the parameter is used —
        // future auditing rules may reference policy.id / autonomyLevel.
        void policy.id;
    }
    async isCollaborationEnabled() {
        const settings = await this.settings.load();
        return settings?.featureFlags?.collaboration === true;
    }
};
EvaluateSupervisorDecisionUseCase = __decorate([
    injectable(),
    __param(0, inject('ISupervisorAgent')),
    __param(1, inject('ISupervisorDecisionRepository')),
    __param(2, inject('IActivityLogRepository')),
    __param(3, inject('ISettingsRepository')),
    __param(5, inject(EscalateToUserUseCase)),
    __metadata("design:paramtypes", [Object, Object, Object, Object, GetSupervisorPolicyUseCase,
        EscalateToUserUseCase])
], EvaluateSupervisorDecisionUseCase);
export { EvaluateSupervisorDecisionUseCase };
