import { Router } from 'express';
import { execSync } from 'node:child_process';
import { existsSync, readFileSync } from 'node:fs';
import { join } from 'node:path';

type KeepaliveStatus = {
  checkedAt?: string;
  status?: 'IDLE' | 'HEALTHY' | 'STALE' | 'MISSING' | string;
  heartbeatAgeSeconds?: number | null;
  lastStep?: string | null;
  historyCount?: number;
  shouldRecover?: boolean;
  activeSessionLabel?: string | null;
  reason?: string;
};

type WorkerHeartbeat = {
  timestamp?: string;
  step?: string;
  status?: string;
  note?: string;
};

type GitCommitSummary = {
  hash: string;
  message: string;
  timestamp: string;
  relative: string;
};

function safeReadJson<T>(path: string): T | null {
  try {
    if (!existsSync(path)) return null;
    return JSON.parse(readFileSync(path, 'utf8')) as T;
  } catch {
    return null;
  }
}

function parseActiveV1Todo(todoText: string): { checked: number; unchecked: number; nextTask: string | null } {
  const activeStart = todoText.indexOf('## 🎯 Active Tasks — v1.0 Recipe Import');
  const backlogStart = todoText.indexOf('## 📋 Backlog (Post-v1)');

  if (activeStart < 0 || backlogStart < 0 || backlogStart <= activeStart) {
    return { checked: 0, unchecked: 0, nextTask: null };
  }

  const activeSection = todoText.slice(activeStart, backlogStart);
  const lines = activeSection.split('\n').map((line) => line.trim());

  const checked = lines.filter((line) => line.startsWith('- [x]')).length;
  const uncheckedLines = lines.filter((line) => line.startsWith('- [ ]'));

  return {
    checked,
    unchecked: uncheckedLines.length,
    nextTask: uncheckedLines[0]?.replace(/^- \[ \] /, '') ?? null,
  };
}

function getLastCommit(projectRoot: string): GitCommitSummary | null {
  try {
    const format = '%H|%s|%cI|%cr';
    const raw = execSync(`git -C "${projectRoot}" log -1 --pretty=format:${format}`, {
      encoding: 'utf8',
      stdio: ['ignore', 'pipe', 'ignore'],
    }).trim();

    const [hash, message, timestamp, relative] = raw.split('|');
    if (!hash || !message || !timestamp || !relative) return null;

    return { hash: hash.slice(0, 8), message, timestamp, relative };
  } catch {
    return null;
  }
}

export function createHarnessRoutes(projectRoot = process.cwd()): Router {
  const router = Router();

  router.get('/status', (_req, res) => {
    try {
      const todoPath = join(projectRoot, 'TODO.md');
      const keepalivePath = join(projectRoot, '.harness', 'keepalive.json');
      const workerHeartbeatPath = join(projectRoot, '.harness', 'worker-heartbeat.json');
      const workerHistoryPath = join(projectRoot, '.harness', 'worker-heartbeat-history.json');

      const todoText = existsSync(todoPath) ? readFileSync(todoPath, 'utf8') : '';
      const todo = parseActiveV1Todo(todoText);

      const keepalive = safeReadJson<KeepaliveStatus>(keepalivePath) ?? { status: 'MISSING' };
      const workerHeartbeat = safeReadJson<WorkerHeartbeat>(workerHeartbeatPath);
      const history = safeReadJson<WorkerHeartbeat[]>(workerHistoryPath) ?? [];

      const data = {
        projectRoot,
        commit: getLastCommit(projectRoot),
        todo,
        keepalive,
        workerHeartbeat,
        workerHeartbeatHistory: Array.isArray(history) ? history.slice(-5) : [],
      };

      res.status(200).json({ success: true, data, error: null });
    } catch (error) {
      const message = error instanceof Error ? error.message : 'Internal server error';
      res.status(500).json({ success: false, data: null, error: message });
    }
  });

  return router;
}
