import fs from 'node:fs';
import path from 'node:path';
import os from 'node:os';

export interface HistoricalPrompt {
  uuid: string;
  sessionId: string;
  cwd: string;
  submittedAt: string;
  text: string;
}

function claudeProjectsDir(): string {
  return path.join(os.homedir(), '.claude', 'projects');
}

/** Every *.jsonl session transcript across every Claude Code project directory. */
export function findTranscriptFiles(): string[] {
  const root = claudeProjectsDir();

  if (!fs.existsSync(root)) {
    return [];
  }

  const files: string[] = [];

  for (const projectDir of fs.readdirSync(root)) {
    const projectPath = path.join(root, projectDir);

    if (!fs.statSync(projectPath).isDirectory()) {
      continue;
    }

    for (const entry of fs.readdirSync(projectPath)) {
      if (entry.endsWith('.jsonl')) {
        files.push(path.join(projectPath, entry));
      }
    }
  }

  return files;
}

// Synthetic system-generated markers that appear as the sole content of a
// "user" text entry - not something the developer actually typed.
const SYNTHETIC_MARKERS = new Set(['[Request interrupted by user]', '[Request interrupted by user for tool use]']);

interface TranscriptEntry {
  type?: string;
  isSidechain?: boolean;
  uuid?: string;
  sessionId?: string;
  cwd?: string;
  timestamp?: string;
  message?: { content?: Array<{ type?: string; text?: string }> };
}

/**
 * A real, human-typed prompt line has type "user", isn't part of a sub-agent
 * sidechain, and its content blocks are all plain text - tool results also
 * show up as type "user" but with a "tool_result" content block, which this
 * excludes.
 */
function isHumanTextEntry(entry: TranscriptEntry): boolean {
  if (entry.type !== 'user' || entry.isSidechain) {
    return false;
  }

  const content = entry.message?.content;

  return Array.isArray(content) && content.length > 0 && content.every((block) => block?.type === 'text');
}

export function extractPromptsFromFile(filePath: string, sinceIso: string): HistoricalPrompt[] {
  const prompts: HistoricalPrompt[] = [];
  const lines = fs.readFileSync(filePath, 'utf8').split('\n');

  for (const line of lines) {
    const trimmed = line.trim();

    if (!trimmed) {
      continue;
    }

    let entry: TranscriptEntry;

    try {
      entry = JSON.parse(trimmed);
    } catch {
      continue;
    }

    if (!isHumanTextEntry(entry)) {
      continue;
    }

    if (!entry.timestamp || entry.timestamp < sinceIso || !entry.sessionId || !entry.uuid || !entry.cwd) {
      continue;
    }

    const text = (entry.message!.content ?? [])
      .map((block) => block.text ?? '')
      .join('\n\n')
      .trim();

    if (!text || SYNTHETIC_MARKERS.has(text)) {
      continue;
    }

    prompts.push({
      uuid: entry.uuid,
      sessionId: entry.sessionId,
      cwd: entry.cwd,
      submittedAt: entry.timestamp,
      text,
    });
  }

  return prompts;
}
