#!/usr/bin/env node
'use strict';

const fs = require('fs');
const os = require('os');
const path = require('path');
const { createStateStore } = require('./lib/state-store');

function showHelp(exitCode = 0) {
  console.log(`
Usage: node scripts/status.js [--db <path>] [--json|--markdown] [--write <path>] [--limit <n>] [--exit-code]

Query the ECC SQLite state store for active sessions, recent skill runs,
install health, pending governance events, and linked work items.

Use --exit-code to return 2 when readiness needs attention.
`);
  process.exit(exitCode);
}

function parseArgs(argv) {
  const args = argv.slice(2);
  const parsed = {
    dbPath: null,
    json: false,
    markdown: false,
    writePath: null,
    exitCode: false,
    help: false,
    limit: 5,
  };

  for (let index = 0; index < args.length; index += 1) {
    const arg = args[index];

    if (arg === '--db') {
      parsed.dbPath = args[index + 1] || null;
      index += 1;
    } else if (arg === '--json') {
      parsed.json = true;
    } else if (arg === '--markdown') {
      parsed.markdown = true;
    } else if (arg === '--exit-code') {
      parsed.exitCode = true;
    } else if (arg === '--write') {
      parsed.writePath = args[index + 1] || null;
      index += 1;
    } else if (arg === '--limit') {
      parsed.limit = args[index + 1] || null;
      index += 1;
    } else if (arg === '--help' || arg === '-h') {
      parsed.help = true;
    } else {
      throw new Error(`Unknown argument: ${arg}`);
    }
  }

  if (parsed.json && parsed.markdown) {
    throw new Error('Choose only one output format: --json or --markdown');
  }

  if (args.includes('--db') && !parsed.dbPath) {
    throw new Error('Missing value for --db');
  }

  if (args.includes('--write') && !parsed.writePath) {
    throw new Error('Missing value for --write');
  }

  if (args.includes('--limit') && !parsed.limit) {
    throw new Error('Missing value for --limit');
  }

  return parsed;
}

function printActiveSessions(section) {
  console.log(`Active sessions: ${section.activeCount}`);
  if (section.sessions.length === 0) {
    console.log('  - none');
    return;
  }

  for (const session of section.sessions) {
    console.log(`  - ${session.id} [${session.harness}/${session.adapterId}] ${session.state}`);
    console.log(`    Repo: ${session.repoRoot || '(unknown)'}`);
    console.log(`    Started: ${session.startedAt || '(unknown)'}`);
    console.log(`    Workers: ${session.workerCount}`);
  }
}

function printSkillRuns(section) {
  const summary = section.summary;
  const successRate = summary.successRate === null ? 'n/a' : `${summary.successRate}%`;
  const failureRate = summary.failureRate === null ? 'n/a' : `${summary.failureRate}%`;

  console.log(`Skill runs (last ${section.windowSize}):`);
  console.log(`  Success: ${summary.successCount}`);
  console.log(`  Failure: ${summary.failureCount}`);
  console.log(`  Unknown: ${summary.unknownCount}`);
  console.log(`  Success rate: ${successRate}`);
  console.log(`  Failure rate: ${failureRate}`);

  if (section.recent.length === 0) {
    console.log('  Recent runs: none');
    return;
  }

  console.log('  Recent runs:');
  for (const skillRun of section.recent.slice(0, 5)) {
    console.log(`  - ${skillRun.id} ${skillRun.outcome} ${skillRun.skillId}@${skillRun.skillVersion}`);
  }
}

function printInstallHealth(section) {
  console.log(`Install health: ${section.status}`);
  console.log(`  Targets recorded: ${section.totalCount}`);
  console.log(`  Healthy: ${section.healthyCount}`);
  console.log(`  Warning: ${section.warningCount}`);

  if (section.installations.length === 0) {
    console.log('  Installations: none');
    return;
  }

  console.log('  Installations:');
  for (const installation of section.installations.slice(0, 5)) {
    console.log(`  - ${installation.targetId} ${installation.status}`);
    console.log(`    Root: ${installation.targetRoot}`);
    console.log(`    Profile: ${installation.profile || '(custom)'}`);
    console.log(`    Modules: ${installation.moduleCount}`);
    console.log(`    Source version: ${installation.sourceVersion || '(unknown)'}`);
  }
}

function printGovernance(section) {
  console.log(`Pending governance events: ${section.pendingCount}`);
  if (section.events.length === 0) {
    console.log('  - none');
    return;
  }

  for (const event of section.events) {
    console.log(`  - ${event.id} ${event.eventType}`);
    console.log(`    Session: ${event.sessionId || '(none)'}`);
    console.log(`    Created: ${event.createdAt}`);
  }
}

function printWorkItems(section) {
  console.log(`Work items: ${section.openCount} open, ${section.blockedCount} blocked, ${section.closedCount} closed`);
  if (section.items.length === 0) {
    console.log('  - none');
    return;
  }

  for (const item of section.items.slice(0, 10)) {
    const sourceId = item.sourceId ? `#${item.sourceId}` : item.id;
    console.log(`  - ${item.source}/${sourceId} ${item.status}: ${item.title}`);
    console.log(`    Owner: ${item.owner || '(unassigned)'}`);
    console.log(`    Updated: ${item.updatedAt}`);
    if (item.url) {
      console.log(`    URL: ${item.url}`);
    }
  }
}

function printReadiness(section) {
  console.log(`Readiness: ${section.status}`);
  console.log(`  Attention items: ${section.attentionCount}`);
  console.log(`  Active sessions: ${section.activeSessions}`);
  console.log(`  Failed skill runs: ${section.failedSkillRuns}`);
  console.log(`  Warning installs: ${section.warningInstallations}`);
  console.log(`  Pending governance: ${section.pendingGovernanceEvents}`);
  console.log(`  Blocked work items: ${section.blockedWorkItems}`);
}

function printHuman(payload) {
  console.log('ECC status\n');
  console.log(`Database: ${payload.dbPath}\n`);
  printReadiness(payload.readiness);
  console.log();
  printActiveSessions(payload.activeSessions);
  console.log();
  printSkillRuns(payload.skillRuns);
  console.log();
  printInstallHealth(payload.installHealth);
  console.log();
  printGovernance(payload.governance);
  console.log();
  printWorkItems(payload.workItems);
}

function formatPercent(value) {
  return value === null ? 'n/a' : `${value}%`;
}

function formatCode(value) {
  return `\`${String(value || '').replace(/`/g, '\\`')}\``;
}

function renderMarkdown(payload) {
  const lines = [
    '# ECC Status',
    '',
    `Generated: ${payload.generatedAt}`,
    `Database: ${formatCode(payload.dbPath)}`,
    '',
    '## Readiness',
    '',
    `Status: ${payload.readiness.status}`,
    `Attention items: ${payload.readiness.attentionCount}`,
    `Active sessions: ${payload.readiness.activeSessions}`,
    `Failed skill runs: ${payload.readiness.failedSkillRuns}`,
    `Warning installs: ${payload.readiness.warningInstallations}`,
    `Pending governance: ${payload.readiness.pendingGovernanceEvents}`,
    `Blocked work items: ${payload.readiness.blockedWorkItems}`,
    '',
    '## Active Sessions',
    '',
    `Active sessions: ${payload.activeSessions.activeCount}`,
  ];

  if (payload.activeSessions.sessions.length === 0) {
    lines.push('- none');
  } else {
    for (const session of payload.activeSessions.sessions) {
      lines.push(`- ${formatCode(session.id)} [${session.harness}/${session.adapterId}] ${session.state}`);
      lines.push(`  - Repo: ${session.repoRoot || '(unknown)'}`);
      lines.push(`  - Started: ${session.startedAt || '(unknown)'}`);
      lines.push(`  - Workers: ${session.workerCount}`);
    }
  }

  const skillSummary = payload.skillRuns.summary;
  lines.push(
    '',
    '## Skill Runs',
    '',
    `Window size: ${payload.skillRuns.windowSize}`,
    `Success: ${skillSummary.successCount}`,
    `Failure: ${skillSummary.failureCount}`,
    `Unknown: ${skillSummary.unknownCount}`,
    `Success rate: ${formatPercent(skillSummary.successRate)}`,
    `Failure rate: ${formatPercent(skillSummary.failureRate)}`
  );

  if (payload.skillRuns.recent.length === 0) {
    lines.push('', 'Recent runs: none');
  } else {
    lines.push('', 'Recent runs:');
    for (const skillRun of payload.skillRuns.recent.slice(0, 5)) {
      lines.push(`- ${formatCode(skillRun.id)} ${skillRun.outcome} ${skillRun.skillId}@${skillRun.skillVersion}`);
    }
  }

  lines.push(
    '',
    '## Install Health',
    '',
    `Install health: ${payload.installHealth.status}`,
    `Targets recorded: ${payload.installHealth.totalCount}`,
    `Healthy: ${payload.installHealth.healthyCount}`,
    `Warning: ${payload.installHealth.warningCount}`
  );

  if (payload.installHealth.installations.length === 0) {
    lines.push('', 'Installations: none');
  } else {
    lines.push('', 'Installations:');
    for (const installation of payload.installHealth.installations.slice(0, 5)) {
      lines.push(`- ${formatCode(installation.targetId)} ${installation.status}`);
      lines.push(`  - Root: ${installation.targetRoot}`);
      lines.push(`  - Profile: ${installation.profile || '(custom)'}`);
      lines.push(`  - Modules: ${installation.moduleCount}`);
      lines.push(`  - Source version: ${installation.sourceVersion || '(unknown)'}`);
    }
  }

  lines.push(
    '',
    '## Governance',
    '',
    `Pending governance events: ${payload.governance.pendingCount}`
  );

  if (payload.governance.events.length === 0) {
    lines.push('- none');
  } else {
    for (const event of payload.governance.events) {
      lines.push(`- ${formatCode(event.id)} ${event.eventType}`);
      lines.push(`  - Session: ${event.sessionId || '(none)'}`);
      lines.push(`  - Created: ${event.createdAt}`);
    }
  }

  lines.push(
    '',
    '## Work Items',
    '',
    `Open: ${payload.workItems.openCount}`,
    `Blocked: ${payload.workItems.blockedCount}`,
    `Closed: ${payload.workItems.closedCount}`
  );

  if (payload.workItems.items.length === 0) {
    lines.push('', '- none');
  } else {
    lines.push('', 'Recent work items:');
    for (const item of payload.workItems.items.slice(0, 10)) {
      const sourceId = item.sourceId ? `#${item.sourceId}` : item.id;
      lines.push(`- ${formatCode(item.source)} ${formatCode(sourceId)} ${item.status}: ${item.title}`);
      lines.push(`  - Owner: ${item.owner || '(unassigned)'}`);
      lines.push(`  - Updated: ${item.updatedAt}`);
      if (item.url) {
        lines.push(`  - URL: ${item.url}`);
      }
    }
  }

  return `${lines.join('\n')}\n`;
}

function writeOutput(writePath, output) {
  const absolutePath = path.resolve(writePath);
  fs.mkdirSync(path.dirname(absolutePath), { recursive: true });
  fs.writeFileSync(absolutePath, output, 'utf8');
}

async function main() {
  let store = null;

  try {
    const options = parseArgs(process.argv);
    if (options.help) {
      showHelp(0);
    }

    store = await createStateStore({
      dbPath: options.dbPath,
      homeDir: process.env.HOME || os.homedir(),
    });

    const payload = {
      dbPath: store.dbPath,
      ...store.getStatus({
        activeLimit: options.limit,
        recentSkillRunLimit: 20,
        pendingLimit: options.limit,
        workItemLimit: options.limit,
      }),
    };

    if (options.json) {
      const output = `${JSON.stringify(payload, null, 2)}\n`;
      if (options.writePath) {
        writeOutput(options.writePath, output);
      }
      process.stdout.write(output);
    } else if (options.markdown) {
      const output = renderMarkdown(payload);
      if (options.writePath) {
        writeOutput(options.writePath, output);
      }
      process.stdout.write(output);
    } else {
      if (options.writePath) {
        throw new Error('--write requires --json or --markdown');
      }
      printHuman(payload);
    }

    if (options.exitCode && payload.readiness.status !== 'ok') {
      process.exitCode = 2;
    }
  } catch (error) {
    console.error(`Error: ${error.message}`);
    process.exit(1);
  } finally {
    if (store) {
      store.close();
    }
  }
}

if (require.main === module) {
  main();
}

module.exports = {
  main,
  parseArgs,
  renderMarkdown,
};
