"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.showDoctor = showDoctor;
const node_fs_1 = require("node:fs");
const clientInfo_1 = require("../clientInfo");
const config_1 = require("../config");
const output_1 = require("../output");
const shellProbe_1 = require("../shellProbe");
const versionCompare_1 = require("../versionCompare");
const clients_1 = require("./clients");
const agents_1 = require("./agents");
const workspaces_1 = require("./workspaces");
async function showDoctor(options = {}) {
    const section = normalizeSection(options.section);
    if (options.section && !section) {
        console.error(`Unknown doctor section "${options.section}". Expected clients, agents, or workspaces.`);
        process.exitCode = 1;
        return null;
    }
    const providers = options.providers ?? {};
    const includeClients = !section || section === 'clients';
    const includeAgents = !section || section === 'agents';
    const includeWorkspaces = !section || section === 'workspaces';
    const [cli, account, tools, clients, agents, workspaces] = await Promise.all([
        providers.cli ? providers.cli() : getCliHealth(),
        providers.account ? providers.account() : getAccountHealth(),
        providers.tools ? providers.tools() : getToolsHealth(),
        includeClients ? (providers.clients ? providers.clients() : (0, clients_1.getClientStatus)()) : Promise.resolve(undefined),
        includeAgents ? (providers.agents ? providers.agents() : (0, agents_1.getAgentsStatus)()) : Promise.resolve(undefined),
        includeWorkspaces ? (providers.workspaces ? providers.workspaces() : Promise.resolve(buildWorkspaceDoctorStatus(options.cwd))) : Promise.resolve(undefined),
    ]);
    const report = {
        cli,
        account,
        tools,
        clients,
        agents,
        workspaces,
        nextActions: collectNextActions(cli, clients, agents, workspaces),
    };
    if (options.json) {
        (0, output_1.printJson)(report);
    }
    else {
        printDoctorReport(report);
    }
    return report;
}
function normalizeSection(value) {
    if (!value) {
        return null;
    }
    return value === 'clients' || value === 'agents' || value === 'workspaces' ? value : null;
}
async function getAccountHealth() {
    const session = (0, config_1.getCurrentAccountSession)((0, config_1.loadConfig)());
    if (!session) {
        return { loggedIn: false };
    }
    return { loggedIn: true, identity: `${session.username} (${session.env})` };
}
async function getCliHealth() {
    const currentVersion = (0, clientInfo_1.getCliVersion)();
    const result = (0, shellProbe_1.runShell)('npm view @playdrop/playdrop-cli version --json');
    if (result.exitCode !== 0 || !result.output.trim()) {
        return {
            version: (0, clientInfo_1.getCliVersionLabel)(),
            updateStatus: 'unknown',
        };
    }
    const latestVersion = parseNpmVersion(result.output);
    if (!latestVersion) {
        return {
            version: (0, clientInfo_1.getCliVersionLabel)(),
            updateStatus: 'unknown',
        };
    }
    const updateAvailable = (0, versionCompare_1.firstVersionIsNewer)(latestVersion, currentVersion);
    return {
        version: (0, clientInfo_1.getCliVersionLabel)(),
        latestVersion,
        updateStatus: updateAvailable ? 'update-available' : 'current',
        updateAvailable,
        nextAction: updateAvailable ? 'playdrop update' : undefined,
    };
}
function parseNpmVersion(output) {
    const trimmed = output.trim();
    try {
        const parsed = JSON.parse(trimmed);
        return typeof parsed === 'string' && parsed.trim().length > 0 ? parsed.trim() : undefined;
    }
    catch {
        return trimmed.length > 0 ? trimmed.split('\n')[0]?.trim() : undefined;
    }
}
async function getToolsHealth() {
    const [node, npm, git] = await Promise.all([
        detectTool('node', ['--version']),
        detectTool('npm', ['--version']),
        detectGit(),
    ]);
    return { node, npm, git };
}
async function detectTool(command, versionArgs) {
    const pathProbe = (0, shellProbe_1.runShell)((0, shellProbe_1.buildCommandPathProbe)(command));
    if (pathProbe.exitCode !== 0 || !pathProbe.output) {
        return { installed: false };
    }
    const version = (0, shellProbe_1.runShell)([command, ...versionArgs].join(' '));
    return {
        installed: true,
        path: pathProbe.output.split('\n')[0]?.trim(),
        version: version.exitCode === 0 ? version.output.split('\n')[0]?.trim() : undefined,
    };
}
async function detectGit() {
    const status = await detectTool('git', ['--version']);
    if (!status.installed) {
        return status;
    }
    const email = (0, shellProbe_1.runShell)('git config --global --get user.email').output.trim();
    const name = (0, shellProbe_1.runShell)('git config --global --get user.name').output.trim();
    const identity = email ? (name ? `${name} <${email}>` : email) : name || undefined;
    return { ...status, identity };
}
function buildWorkspaceDoctorStatus(cwd) {
    const cache = (0, workspaces_1.loadWorkspaceCacheWithCurrentContext)({ cwd });
    return {
        ...cache,
        defaultWorkspacePath: cache.defaultWorkspacePath,
        workspaces: cache.workspaces.map((workspace) => ({
            ...workspace,
            exists: (0, node_fs_1.existsSync)(workspace.path),
        })),
    };
}
function collectNextActions(cli, clients, agents, workspaces) {
    const actions = [];
    if (cli.nextAction) {
        actions.push(cli.nextAction);
    }
    if (clients?.nextAction) {
        actions.push(clients.nextAction);
    }
    for (const agent of agents?.agents ?? []) {
        if (agent.nextAction?.command) {
            actions.push(agent.nextAction.command);
        }
    }
    if (workspaces && workspaces.workspaces.length === 0) {
        actions.push(recommendedWorkspaceRefreshCommand());
        actions.push('playdrop workspaces init');
    }
    return [...new Set(actions)];
}
function recommendedWorkspaceRefreshCommand() {
    return (0, workspaces_1.getWorkspaceRefreshExample)();
}
function printDoctorReport(report) {
    const cliUpdate = report.cli.updateStatus === 'update-available'
        ? `, update available: ${report.cli.latestVersion}`
        : report.cli.updateStatus === 'current'
            ? ', current'
            : ', update status unknown';
    console.log(`PlayDrop CLI: ${report.cli.version}${cliUpdate}`);
    console.log(`Account: ${report.account.loggedIn ? report.account.identity ?? 'logged in' : 'not logged in'}`);
    console.log(`Node: ${report.tools.node.installed ? report.tools.node.version ?? 'installed' : 'missing'}`);
    console.log(`npm: ${report.tools.npm.installed ? report.tools.npm.version ?? 'installed' : 'missing'}`);
    console.log(`Git: ${report.tools.git.installed ? report.tools.git.identity ?? report.tools.git.version ?? 'installed' : 'missing'}`);
    if (report.clients) {
        printNativeClientDoctorStatus(report.clients);
    }
    if (report.agents) {
        printAgentsDoctorStatus(report.agents);
    }
    if (report.workspaces) {
        if (report.workspaces.workspaces.length === 0) {
            (0, workspaces_1.printNoCachedWorkspacesGuidance)(report.workspaces.defaultWorkspacePath);
        }
        else {
            console.log(`Cached workspaces: ${report.workspaces.workspaces.length}`);
            if (report.workspaces.currentWorkspacePath) {
                console.log(`Current workspace: ${report.workspaces.currentWorkspacePath}`);
            }
        }
    }
    if (report.nextActions.length > 0) {
        console.log('Next actions:');
        for (const action of report.nextActions) {
            console.log(`  Run: ${action}`);
        }
    }
}
function printNativeClientDoctorStatus(status) {
    if (!status.supported) {
        console.log(`Native client: unavailable on ${status.platform}`);
        return;
    }
    if (!status.installed) {
        console.log('Native client: missing');
        return;
    }
    const statusLabel = status.updateAvailable ? 'update available' : 'up to date';
    console.log(`Native client: ${statusLabel}`);
    console.log(`  Installed: ${formatVersionBuild(status.version, status.build)}`);
    if (status.latestVersion || status.latestBuild) {
        console.log(`  Latest: ${formatVersionBuild(status.latestVersion, status.latestBuild)}`);
    }
    if (status.appPath) {
        console.log(`  Location: ${status.appPath}`);
    }
}
function printAgentsDoctorStatus(status) {
    console.log('Agents:');
    if (status.agents.length === 0) {
        console.log('  none detected');
        return;
    }
    for (const agent of status.agents) {
        console.log(`  ${agent.name}`);
        console.log(`    App: ${agent.app.installed ? agent.app.path ? `installed at ${agent.app.path}` : 'installed' : 'missing'}`);
        console.log(`    CLI: ${formatAgentCli(agent.cli)}`);
        console.log(`    Account: ${formatAgentAccount(agent.account)}`);
        console.log(`    Plugin: ${formatAgentPlugin(agent.plugin)}`);
    }
}
function formatVersionBuild(version, build) {
    if (version && build) {
        return `${version} (build ${build})`;
    }
    return version ?? build ?? 'unknown';
}
function formatAgentCli(cli) {
    if (!cli.installed) {
        return 'missing';
    }
    const label = cli.version ?? 'installed';
    return cli.path ? `${label} at ${cli.path}` : label;
}
function formatAgentAccount(account) {
    if (account?.identity) {
        return account.subscription ? `${account.identity} (${account.subscription})` : account.identity;
    }
    if (account?.signedIn === false) {
        return 'not signed in';
    }
    return 'unknown';
}
function formatAgentPlugin(plugin) {
    if (plugin.status === 'manual-verification-required') {
        return plugin.latestVersion ? `manual verification required, latest: ${plugin.latestVersion}` : 'manual verification required';
    }
    if (plugin.status === 'unknown') {
        return plugin.message ? `unknown (${plugin.message})` : 'unknown';
    }
    if (!plugin.installed) {
        return plugin.latestVersion ? `missing, latest: ${plugin.latestVersion}` : 'missing';
    }
    const installedVersion = plugin.version ?? 'installed';
    const enabled = plugin.status === 'activation-required' || plugin.enabled === false ? ', activation required' : '';
    if (plugin.updateAvailable) {
        return `${installedVersion}${enabled}, update available: ${plugin.latestVersion ?? 'unknown'}`;
    }
    return `${installedVersion}${enabled}, up to date`;
}
