/**
 * src/autonomy/escalation.ts
 *
 * When a policy says "ask first," Muassis composes an escalation:
 *   • Title — what's at stake
 *   • Context — why the situation arose
 *   • Recommendation — Muassis's call
 *   • Counterargument — the strongest case for the OTHER answer
 *   • Alternatives — viable middle paths
 *
 * The owner sees a structured decision card, not a vague "should I do this?"
 * The counterargument is what makes Muassis feel like a partner, not a yes-bot.
 */
import { randomUUID } from 'node:crypto';
import { supabase } from '../utils/supabase.js';
import { createChildLogger } from '../utils/logger.js';
import { record as journalRecord } from './journal.js';
const log = createChildLogger('autonomy:escalation');
export async function escalate(input) {
    const id = randomUUID();
    const now = new Date();
    const expiresAt = new Date(now.getTime() + (input.expiresInMinutes ?? 30) * 60 * 1000);
    const row = {
        id,
        tenant_id: input.tenantId,
        approval_request_id: input.approvalRequestId ?? null,
        title: input.title,
        context: input.context,
        recommendation: input.recommendation,
        counterargument: input.counterargument ?? null,
        alternatives: input.alternatives ?? [],
        risk_level: input.riskLevel ?? 'medium',
        status: 'pending',
        resolution: null,
        expires_at: expiresAt.toISOString(),
        created_at: now.toISOString(),
        resolved_at: null,
    };
    const { error } = await supabase.from('escalation_queue').insert(row);
    if (error)
        throw new Error(`escalate failed: ${error.message}`);
    await journalRecord({
        tenantId: input.tenantId,
        kind: 'escalation',
        action: input.title,
        outcome: 'escalated',
        reason: input.recommendation,
        metadata: {
            escalation_id: id,
            risk_level: row.risk_level,
            alternatives_count: row.alternatives.length,
        },
    });
    log.info({ tenantId: input.tenantId, id, title: input.title, risk: row.risk_level }, 'escalation queued');
    return row;
}
export async function listPending(tenantId) {
    const { data, error } = await supabase
        .from('escalation_queue')
        .select('*')
        .eq('tenant_id', tenantId)
        .eq('status', 'pending')
        .order('created_at', { ascending: false })
        .limit(50);
    if (error) {
        log.warn({ error: error.message }, 'listPending failed');
        return [];
    }
    // Filter expired ones lazily so the dashboard never sees stale entries.
    const now = Date.now();
    return (data ?? []).filter(e => new Date(e.expires_at).getTime() > now);
}
export async function resolve(tenantId, escalationId, resolution, note) {
    const now = new Date().toISOString();
    const { data: existing } = await supabase
        .from('escalation_queue')
        .select('*')
        .eq('tenant_id', tenantId)
        .eq('id', escalationId)
        .maybeSingle();
    if (!existing)
        return null;
    const patch = {
        status: 'resolved',
        resolution: note ? `${resolution}: ${note}` : resolution,
        resolved_at: now,
    };
    const { error } = await supabase
        .from('escalation_queue')
        .update(patch)
        .eq('tenant_id', tenantId)
        .eq('id', escalationId);
    if (error) {
        log.warn({ error: error.message }, 'escalation resolve failed');
        return null;
    }
    await journalRecord({
        tenantId,
        kind: 'escalation_resolved',
        action: existing.title,
        outcome: resolution === 'denied' ? 'declined' : 'success',
        reason: patch.resolution,
        metadata: { escalation_id: escalationId, resolution },
    });
    return { ...existing, ...patch };
}
/** Render an escalation as plain text suitable for WhatsApp / web chat banner. */
export function formatEscalation(esc, opts = {}) {
    const riskEmoji = {
        low: '🟢',
        medium: '🟡',
        high: '🟠',
        critical: '🔴',
    }[esc.risk_level];
    if (opts.short) {
        return `${riskEmoji} ${esc.title} — ${esc.recommendation}`;
    }
    const parts = [
        `${riskEmoji} *Decision needed: ${esc.title}*`,
        '',
        `*Context*: ${esc.context}`,
        '',
        `*My recommendation*: ${esc.recommendation}`,
    ];
    if (esc.counterargument) {
        parts.push('', `*Counterargument*: ${esc.counterargument}`);
    }
    if (esc.alternatives && esc.alternatives.length > 0) {
        parts.push('', '*Alternatives*:');
        for (const alt of esc.alternatives) {
            parts.push(`  • ${alt}`);
        }
    }
    parts.push('', `Reply: ✅ approve · ❌ deny · ✏️ modify · expires ${new Date(esc.expires_at).toLocaleTimeString('en-GB', { hour: '2-digit', minute: '2-digit' })}`);
    return parts.join('\n');
}
//# sourceMappingURL=escalation.js.map