/**
 * Dashboard Data Aggregation
 *
 * Gathers data from board, agents, sessions, and PRs into a unified interface
 * for the web dashboard.
 */
import * as path from 'node:path';
import { execSync } from 'node:child_process';
import Database from 'better-sqlite3';
import { getWorkspaceInfo, getAllAgentsStatus, getAgentTmuxSessions } from '../agents/commands.js';
import { ExecutionStorage } from '../execution/index.js';
import { getHostTmuxSessionNames, parseSessionName, getContainerTmuxSessionMap, flattenContainerSessions, findContainerSessionsByPrefix, findSessionForExecution, } from '../execution/session-utils.js';
import { listOpenPRs } from '../pr/index.js';
// =============================================================================
// PR CI Status Cache (gh CLI is slow)
// =============================================================================
let prCacheData = null;
const PR_CACHE_TTL_MS = 30_000;
// =============================================================================
// Data Gathering Functions
// =============================================================================
export async function gatherBoardData(storage, projectId) {
    try {
        const board = await storage.getBoard(projectId);
        const columns = board.columns.map((col) => ({
            id: col.id,
            name: col.name,
            position: col.position,
            tickets: (col.tickets || []).map((t) => ({
                id: t.id,
                title: t.title,
                priority: t.priority,
                category: t.category,
                assignee: t.assignee,
                statusName: t.statusName,
                labels: t.labels || [],
            })),
        }));
        return { columns };
    }
    catch {
        return { columns: [] };
    }
}
export function gatherAgentData() {
    try {
        const workspaceInfo = getWorkspaceInfo();
        const statuses = getAllAgentsStatus(workspaceInfo);
        return statuses.map((s) => {
            let hasActiveSessions = false;
            try {
                hasActiveSessions = getAgentTmuxSessions(s.name).length > 0;
            }
            catch {
                // tmux not available
            }
            return {
                name: s.name,
                exists: s.exists,
                branch: s.branch,
                assignedTickets: s.assignedTickets,
                completedTickets: s.completedTickets,
                hasActiveSessions,
            };
        });
    }
    catch {
        return [];
    }
}
export function gatherSessionData() {
    let executionStorage = null;
    let db = null;
    const sessions = [];
    try {
        const workspaceInfo = getWorkspaceInfo();
        const dbPath = path.join(workspaceInfo.path, '.proletariat', 'workspace.db');
        db = new Database(dbPath);
        executionStorage = new ExecutionStorage(db);
    }
    catch {
        // Not in workspace — still discover tmux sessions below
    }
    try {
        const runningExecutions = executionStorage?.listExecutions({ status: 'running' }) || [];
        const startingExecutions = executionStorage?.listExecutions({ status: 'starting' }) || [];
        const activeExecutions = [...runningExecutions, ...startingExecutions];
        executionStorage?.cleanupStaleExecutions();
        const hostTmuxSessions = getHostTmuxSessionNames();
        const containerTmuxSessions = getContainerTmuxSessionMap();
        const allContainerSessions = flattenContainerSessions(containerTmuxSessions);
        const matchedHostSessions = new Set();
        const matchedContainerSessions = new Set();
        for (const exec of activeExecutions) {
            const isContainer = exec.environment === 'devcontainer';
            let exists = false;
            let containerId;
            let actualSessionId = exec.sessionId;
            if (!exec.sessionId) {
                if (isContainer && exec.containerId) {
                    const containerSessions = findContainerSessionsByPrefix(containerTmuxSessions, exec.containerId);
                    const match = findSessionForExecution(exec.ticketId, exec.agentName, containerSessions);
                    if (match) {
                        actualSessionId = match;
                        exists = true;
                        containerId = exec.containerId;
                    }
                }
                else {
                    const match = findSessionForExecution(exec.ticketId, exec.agentName, hostTmuxSessions);
                    if (match) {
                        actualSessionId = match;
                        exists = true;
                    }
                }
                if (!actualSessionId)
                    continue;
            }
            else {
                if (isContainer && exec.containerId) {
                    const containerSessions = findContainerSessionsByPrefix(containerTmuxSessions, exec.containerId);
                    exists = containerSessions.includes(exec.sessionId);
                    containerId = exec.containerId;
                }
                else {
                    exists = hostTmuxSessions.includes(exec.sessionId);
                }
            }
            if (exists && actualSessionId) {
                if (isContainer && containerId) {
                    matchedContainerSessions.add(`${containerId}:${actualSessionId}`);
                }
                else {
                    matchedHostSessions.add(actualSessionId);
                }
            }
            if (actualSessionId && exists) {
                sessions.push({
                    sessionId: actualSessionId,
                    ticketId: exec.ticketId,
                    agentName: exec.agentName,
                    status: exec.status,
                    environment: isContainer ? 'container' : 'host',
                    source: 'db',
                });
            }
        }
        // Discover orphan sessions
        for (const sessionName of hostTmuxSessions) {
            if (matchedHostSessions.has(sessionName))
                continue;
            const parsed = parseSessionName(sessionName);
            if (parsed) {
                sessions.push({
                    sessionId: sessionName,
                    ticketId: parsed.ticketId,
                    agentName: parsed.agentName,
                    status: 'orphan',
                    environment: 'host',
                    source: 'discovered',
                });
            }
        }
        for (const { sessionName } of allContainerSessions) {
            const key = `${sessionName}`;
            // Check all container session entries
            let matched = false;
            for (const k of matchedContainerSessions) {
                if (k.endsWith(`:${sessionName}`)) {
                    matched = true;
                    break;
                }
            }
            if (matched)
                continue;
            const parsed = parseSessionName(sessionName);
            if (parsed) {
                sessions.push({
                    sessionId: sessionName,
                    ticketId: parsed.ticketId,
                    agentName: parsed.agentName,
                    status: 'orphan',
                    environment: 'container',
                    source: 'discovered',
                });
            }
        }
    }
    finally {
        db?.close();
    }
    return sessions;
}
export function gatherPRData() {
    const now = Date.now();
    if (prCacheData && (now - prCacheData.fetchedAt) < PR_CACHE_TTL_MS) {
        return prCacheData.prs;
    }
    try {
        const openPRs = listOpenPRs();
        // Try to get CI status
        let ciMap = new Map();
        try {
            const ciResult = execSync('gh pr list --json number,statusCheckRollup', { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'], timeout: 15_000 });
            const ciData = JSON.parse(ciResult);
            for (const pr of ciData) {
                if (!pr.statusCheckRollup || pr.statusCheckRollup.length === 0) {
                    ciMap.set(pr.number, 'unknown');
                    continue;
                }
                const hasFailure = pr.statusCheckRollup.some((c) => c.conclusion === 'FAILURE' || c.state === 'FAILURE');
                const allSuccess = pr.statusCheckRollup.every((c) => c.conclusion === 'SUCCESS' || c.state === 'SUCCESS');
                const hasPending = pr.statusCheckRollup.some((c) => c.state === 'PENDING' || c.conclusion === '');
                if (hasFailure)
                    ciMap.set(pr.number, 'failure');
                else if (allSuccess)
                    ciMap.set(pr.number, 'success');
                else if (hasPending)
                    ciMap.set(pr.number, 'pending');
                else
                    ciMap.set(pr.number, 'unknown');
            }
        }
        catch {
            // CI status unavailable
        }
        const prs = openPRs.map((pr) => ({
            number: pr.number,
            url: pr.url,
            title: pr.title,
            headBranch: pr.headBranch,
            isDraft: pr.isDraft,
            ciStatus: ciMap.get(pr.number) || 'unknown',
        }));
        prCacheData = { prs, fetchedAt: now };
        return prs;
    }
    catch {
        return prCacheData?.prs || [];
    }
}
export async function gatherDashboardData(storage, projectId, projectName) {
    const [board, agents, sessions, prs] = await Promise.all([
        gatherBoardData(storage, projectId),
        Promise.resolve(gatherAgentData()),
        Promise.resolve(gatherSessionData()),
        Promise.resolve(gatherPRData()),
    ]);
    return {
        projectId,
        projectName,
        timestamp: new Date().toISOString(),
        board,
        agents,
        sessions,
        prs,
    };
}
//# sourceMappingURL=data.js.map