import * as crypto from 'crypto';
import * as path from 'path';
import { Parser, ParsedEvent, inferWorktreeLabel } from './types';
import { estimateCostUsd } from './cost';

/**
 * Codex CLI JSONL parser
 *
 * Codex CLI JSONL 格式与 Claude Code 相似但字段略不同；此实现按目前观察的格式编码：
 *   { "type": "completion", "usage": { "prompt_tokens", "completion_tokens", "cached_tokens" }, "model": "...", "id": "...", "ts": "...", "cwd": "..." }
 * 实测到的真实字段如有差异需要 PR 调整。
 */
export const codexParser: Parser = {
  tool: 'codex-cli',
  parseLine(line, filePath, pricing): ParsedEvent | null {
    let obj: any;
    try {
      obj = JSON.parse(line);
    } catch {
      return null;
    }
    // 接受多种可能的 event 类型
    const isCompletion = obj?.type === 'completion' || obj?.type === 'response' || obj?.usage;
    if (!isCompletion || !obj.usage) return null;

    const model = obj.model ?? 'unknown';
    const inputTokens = Number(obj.usage.prompt_tokens ?? obj.usage.input_tokens ?? 0);
    const outputTokens = Number(obj.usage.completion_tokens ?? obj.usage.output_tokens ?? 0);
    const cacheReadTokens = Number(obj.usage.cached_tokens ?? obj.usage.cache_read_input_tokens ?? 0);
    const cacheCreationTokens = Number(obj.usage.cache_creation_input_tokens ?? 0);

    const sessionId = obj.session_id ?? obj.sessionId ?? path.basename(filePath, '.jsonl');
    const projectPath = obj.cwd ?? path.dirname(filePath);
    const ts = obj.ts ?? obj.timestamp ?? new Date().toISOString();

    const dedupKey = obj.id ?? obj.turn_id ?? crypto.createHash('sha256').update(line).digest('hex').slice(0, 16);
    const rawMessageId = `codex-cli:${sessionId}:${dedupKey}`.slice(0, 128);

    // 隐私铁律：只读 metadata（id/type/name/version/cwd/branch），永不读 content/input/output
    const gitBranch =
      typeof obj.git_branch === 'string' && obj.git_branch
        ? obj.git_branch.slice(0, 255)
        : typeof obj.gitBranch === 'string' && obj.gitBranch
          ? obj.gitBranch.slice(0, 255)
          : undefined;
    const agentVersionEvent =
      typeof obj.version === 'string' && obj.version
        ? obj.version.slice(0, 32)
        : typeof obj.cli_version === 'string' && obj.cli_version
          ? obj.cli_version.slice(0, 32)
          : undefined;
    const worktreeLabel = inferWorktreeLabel(obj.cwd);
    const cwdBasename = obj.cwd ? path.basename(obj.cwd).slice(0, 255) : undefined;
    const stopReason =
      typeof obj.stop_reason === 'string'
        ? obj.stop_reason.slice(0, 32)
        : typeof obj.finish_reason === 'string'
          ? obj.finish_reason.slice(0, 32)
          : undefined;

    // Codex CLI 暂未观察到稳定的 tool_use 块结构，预留字段但默认空
    let toolUseCount: number | undefined;
    let toolNames: string[] | undefined;
    if (Array.isArray(obj.tool_calls)) {
      const set = new Set<string>();
      for (const c of obj.tool_calls) {
        const n = c?.function?.name ?? c?.name;
        if (typeof n === 'string') set.add(n.slice(0, 64));
      }
      if (set.size > 0) {
        toolUseCount = obj.tool_calls.length;
        toolNames = Array.from(set).slice(0, 20);
      }
    }

    return {
      rawMessageId,
      tool: 'codex-cli',
      sessionId,
      projectPath,
      model,
      ts,
      inputTokens,
      outputTokens,
      cacheCreationTokens,
      cacheReadTokens,
      estimatedCostUsd: estimateCostUsd(model, inputTokens, outputTokens, cacheCreationTokens, cacheReadTokens, pricing),
      gitBranch,
      agentVersionEvent,
      worktreeLabel,
      cwdBasename,
      toolUseCount,
      toolNames,
      stopReason,
    };
  },
};
