/**
 * dist/autonomy/autonomous-meeting.js
 *
 * Autonomous AI-Council meetings. Every few hours the agent looks at the real
 * business state (open goals, recent insights/decisions) and decides — cheaply,
 * one LLM call — whether any subject genuinely warrants convening the council.
 * Most cycles decide "no" (1 cheap call → near-zero cost). When a subject DOES
 * warrant it, the full council convenes (visible live in the Office meeting room
 * via /api/council/active) and the outcome + Founder verdict is reported back to
 * the owner on their channel (WhatsApp/Telegram/web).
 *
 * This is what makes the meeting room actually show meetings — the agent detects
 * the need on its own instead of waiting to be asked.
 */
import { createChildLogger } from '../utils/logger.js';
import { callWithFailover } from '../models/failover.js';
import { supabase } from '../utils/supabase.js';
import { record as journalRecord } from './journal.js';
const log = createChildLogger('autonomy:meeting');
function parseJson(s) {
    if (!s)
        return null;
    let c = String(s).trim();
    if (c.startsWith('```'))
        c = c.replace(/^```(?:json)?\n?/, '').replace(/\n?```$/, '').trim();
    try {
        return JSON.parse(c);
    }
    catch { /* try slice */ }
    const a = c.indexOf('{'), b = c.lastIndexOf('}');
    if (a !== -1 && b > a) {
        try {
            return JSON.parse(c.slice(a, b + 1));
        }
        catch { /* nope */ }
    }
    return null;
}
async function gatherContext(tenantId) {
    let goalsText = 'لا يوجد';
    let insightsText = 'لا يوجد';
    try {
        const { data: goals } = await supabase
            .from('agenda_goals').select('*').eq('tenant_id', tenantId).limit(10);
        const open = (goals ?? []).filter((g) => !['done', 'completed', 'cancelled', 'archived'].includes(String(g.status || g.state || '').toLowerCase()));
        if (open.length)
            goalsText = open.map((g) => `- ${g.title || g.goal || g.description || '(هدف)'} [${g.status || g.state || ''}]`).join('\n');
    }
    catch { /* best-effort */ }
    try {
        const { data: ins } = await supabase
            .from('journal_entries').select('kind, action, reason')
            .eq('tenant_id', tenantId)
            .in('kind', ['insight', 'goal_created', 'reflection', 'research', 'skill_installed'])
            .order('created_at', { ascending: false }).limit(10);
        if ((ins ?? []).length)
            insightsText = ins.map((x) => `- ${x.action || ''}${x.reason ? ': ' + x.reason : ''}`).join('\n');
    }
    catch { /* best-effort */ }
    return `الأهداف المفتوحة:\n${goalsText}\n\nأحدث الأفكار والملاحظات والتعلّمات:\n${insightsText}`;
}
/**
 * Decide-then-maybe-convene. Returns { convened, question? }.
 */
export async function runAutonomousMeeting(tenantId) {
    const context = await gatherContext(tenantId);
    // Cheap gate: one call. Default to NO meeting unless something is genuinely
    // strategic — this keeps autonomous meetings rare + cheap.
    const decideSys = `أنت "المؤسس"، المدير التنفيذي. مهمتك أن تقرّر بحياد: هل يوجد الآن موضوع استراتيجي يستحق فعلاً عقد اجتماع مجلس (قرار مهم، مفترق طرق، مقايضة صعبة، خطر، أو فرصة كبيرة)؟ لا تعقد اجتماعاً للأمور الروتينية أو التافهة أو المتكرّرة. كن انتقائياً جداً. أجب بصيغة JSON فقط: {"needed": true أو false, "question": "السؤال الاستراتيجي الواحد المراد نقاشه", "why": "سبب مختصر"}`;
    let decisionRaw = null;
    try {
        const r = await callWithFailover('flash', [{ role: 'system', content: decideSys }, { role: 'user', content: context }], { temperature: 0.3, maxTokens: 300 }, tenantId);
        decisionRaw = r?.content ?? null;
    }
    catch (err) {
        log.warn({ tenantId, err: err.message }, 'meeting decision call failed');
        return { convened: false };
    }
    const decision = parseJson(decisionRaw);
    if (!decision || !decision.needed || !decision.question) {
        log.info({ tenantId, why: decision?.why }, 'autonomous meeting: nothing warrants a council this cycle');
        await journalRecord({
            tenantId, kind: 'meeting_skipped',
            action: 'راجعت الوضع — لا يوجد موضوع يستحق اجتماعاً الآن',
            outcome: 'success', reason: decision?.why || 'لا مواضيع استراتيجية معلّقة',
        }).catch(() => { });
        return { convened: false };
    }
    // Resolve the owner's chat so the meeting + result land in the right thread.
    let customerId = null;
    try {
        const { resolveOwnerPrimaryCustomerId } = await import('../web-chat/owner-thread.js');
        customerId = await resolveOwnerPrimaryCustomerId(tenantId);
    }
    catch { /* falls back to council-only */ }
    // Convene — this populates activeMeetings(tenantId), which the Office meeting
    // room polls live, so the owner SEES the agents meeting.
    let report;
    try {
        const { conveneCouncil } = await import('../agent/council.js');
        report = await conveneCouncil(tenantId, customerId, decision.question);
    }
    catch (err) {
        log.error({ tenantId, err: err.message }, 'autonomous council convene failed');
        return { convened: false };
    }
    // Report findings + Founder verdict back to the owner's channel.
    try {
        const { formatCouncilReport } = await import('../agent/council.js');
        const body = `🏛️ *عقدت اجتماع مجلس تلقائياً* — رصدت موضوعاً يستحق النقاش:\n\n${formatCouncilReport(report)}`;
        if (customerId) {
            const { randomUUID } = await import('node:crypto');
            const nowIso = new Date().toISOString();
            await supabase.from('messages').insert({
                id: randomUUID(), tenant_id: tenantId, customer_id: customerId,
                session_id: `meeting:${Date.now()}`, direction: 'outbound', type: 'text',
                content: body, delivery_status: 'sent', created_at: nowIso,
            }).catch(() => { });
            const { deliverToCustomerChannel } = await import('../delivery/delivery.js');
            await deliverToCustomerChannel(tenantId, customerId, body).catch(() => { });
        }
    }
    catch (err) {
        log.warn({ tenantId, err: err.message }, 'meeting report delivery failed (meeting still held)');
    }
    await journalRecord({
        tenantId, kind: 'meeting_held',
        action: `اجتماع مجلس: ${String(decision.question).slice(0, 80)}`,
        target: decision.question, outcome: 'success',
        reason: (report?.agreement || report?.founderVerdict || '').slice(0, 200),
    }).catch(() => { });
    log.info({ tenantId, question: decision.question }, '🏛️ autonomous council meeting held + reported');
    return { convened: true, question: decision.question };
}
//# sourceMappingURL=autonomous-meeting.js.map
