import { spawn } from 'node:child_process';
import { cleanPrompt } from '../lib/clean-prompt';
import { detectProject } from '../device/project';
import { isPathExcluded, readConfig } from '../config/store';
import { enqueue } from '../storage/queue';

interface ClaudeHookInput {
  session_id?: string;
  cwd?: string;
  prompt?: string;
  hook_event_name?: string;
}

function readStdin(): Promise<string> {
  return new Promise((resolve) => {
    let data = '';

    if (process.stdin.isTTY) {
      resolve('');

      return;
    }

    process.stdin.setEncoding('utf8');
    process.stdin.on('data', (chunk) => (data += chunk));
    process.stdin.on('end', () => resolve(data));
    process.stdin.on('error', () => resolve(data));
  });
}

function triggerBackgroundSync(): void {
  const child = spawn(process.execPath, [process.argv[1], 'sync', '--background'], {
    detached: true,
    stdio: 'ignore',
  });
  child.unref();
}

async function parseInput(): Promise<ClaudeHookInput> {
  const raw = await readStdin();

  if (!raw.trim()) {
    return {};
  }

  try {
    return JSON.parse(raw) as ClaudeHookInput;
  } catch {
    return {};
  }
}

/**
 * The primary hook. Must never block Claude Code: capture -> local SQLite
 * queue -> return. Uploading happens in a detached background process.
 */
export async function handleUserPromptSubmit(): Promise<void> {
  const input = await parseInput();
  const config = readConfig();

  if (!config || !config.enabled || !input.prompt || !input.session_id) {
    return;
  }

  const cwd = input.cwd ?? process.cwd();

  if (isPathExcluded(config, cwd)) {
    return;
  }

  const project = detectProject(cwd);

  if (config.excludedProjects.includes(project.name)) {
    return;
  }

  const cleaned = cleanPrompt(input.prompt);

  if (!cleaned) {
    return;
  }

  enqueue({
    promptId: `${input.session_id}:${Date.now()}:${Math.random().toString(36).slice(2, 8)}`,
    sessionId: input.session_id,
    prompt: cleaned,
    submittedAt: new Date().toISOString(),
    projectName: project.name,
    projectPathHash: project.pathHash,
    projectDetectionSource: project.detectionSource,
    clientVersion: config.agentVersion,
  });

  triggerBackgroundSync();
}

/** Best-effort queue flush at session boundaries; never blocks. */
export async function handleSessionStart(): Promise<void> {
  const config = readConfig();

  if (config?.enabled) {
    triggerBackgroundSync();
  }
}

export async function handleSessionEnd(): Promise<void> {
  const config = readConfig();

  if (config?.enabled) {
    triggerBackgroundSync();
  }
}
