#!/usr/bin/env node

'use strict';

/**
 * log-activity.js — Project activity log writer
 * Appends JSONL entries to .claude/activity.log with rotation.
 *
 * Usage:
 *   node log-activity.js --skill "eck:spec" --feature "user-auth" \
 *     --outcome "success" --duration 342 --summary "FRD.md with 8 ACs" --step "spec"
 */

const fs = require('fs');
const path = require('path');

const MAX_LINES = 500;
const VALID_OUTCOMES = ['success', 'partial', 'failed', 'cancelled'];

// ─── Log File ───────────────────────────────────────────────────────────────

function resolveLogPath() {
  const cwd = process.env.CLAUDE_PROJECT_DIR || process.cwd();
  return path.join(cwd, '.claude', 'activity.log');
}

function countLines(filePath) {
  try {
    const content = fs.readFileSync(filePath, 'utf-8');
    return content.trim().split('\n').filter(Boolean).length;
  } catch {
    return 0;
  }
}

function rotate(filePath) {
  const lineCount = countLines(filePath);
  if (lineCount < MAX_LINES) return;

  const backupPath = filePath + '.1';
  try {
    // Replace backup with current
    if (fs.existsSync(backupPath)) fs.unlinkSync(backupPath);
    fs.renameSync(filePath, backupPath);
  } catch { /* best-effort */ }
}

// ─── Argument Parsing ───────────────────────────────────────────────────────

function parseArgs(argv) {
  const args = {};
  for (let i = 0; i < argv.length; i++) {
    if (argv[i].startsWith('--') && i + 1 < argv.length) {
      const key = argv[i].slice(2);
      args[key] = argv[++i];
    }
  }
  return args;
}

// ─── Append Entry ───────────────────────────────────────────────────────────

function appendEntry(entry, logPath) {
  const filePath = logPath || resolveLogPath();
  const dir = path.dirname(filePath);
  fs.mkdirSync(dir, { recursive: true });

  // Rotate if needed
  rotate(filePath);

  const line = JSON.stringify(entry) + '\n';
  fs.appendFileSync(filePath, line, 'utf-8');
}

// ─── Read Entries ───────────────────────────────────────────────────────────

function readEntries(logPath, options = {}) {
  const filePath = logPath || resolveLogPath();
  try {
    if (!fs.existsSync(filePath)) return [];
    const content = fs.readFileSync(filePath, 'utf-8');
    let entries = content.trim().split('\n').filter(Boolean).map(line => {
      try { return JSON.parse(line); } catch { return null; }
    }).filter(Boolean);

    if (options.skill) {
      entries = entries.filter(e => e.skill && e.skill.includes(options.skill));
    }
    if (options.errors) {
      entries = entries.filter(e => e.outcome === 'failed');
    }
    if (options.today) {
      const today = new Date().toISOString().slice(0, 10);
      entries = entries.filter(e => e.ts && e.ts.startsWith(today));
    }

    return entries;
  } catch {
    return [];
  }
}

// ─── Main ───────────────────────────────────────────────────────────────────

function main() {
  const args = parseArgs(process.argv.slice(2));

  if (!args.skill) {
    console.error('Usage: log-activity.js --skill <skill> --feature <feature> --outcome <outcome> --duration <sec> --summary <text> --step <step>');
    process.exit(1);
  }

  const outcome = args.outcome || 'success';
  if (!VALID_OUTCOMES.includes(outcome)) {
    console.error(`Invalid outcome: ${outcome}. Valid: ${VALID_OUTCOMES.join(', ')}`);
    process.exit(1);
  }

  const entry = {
    ts: new Date().toISOString(),
    skill: args.skill,
    feature: args.feature || null,
    outcome,
    duration_sec: args.duration ? parseInt(args.duration, 10) : null,
    summary: args.summary || null,
    step: args.step || null,
  };

  appendEntry(entry);
}

module.exports = {
  appendEntry,
  readEntries,
  resolveLogPath,
  MAX_LINES,
  VALID_OUTCOMES,
};

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