import fs from "fs";
import path from "path";
import { EVAL_CASES_DIR, PRESETS_DIR, TRACES_DIR } from "../config";
import { ensureDir, writeJsonFile } from "../utils/files";
import type { PromptPreset } from "../types/preset";

export interface TraceRecord {
  trace_id: string;
  timestamp: string;
  model: string;
  prompt_version: string;
  schema_version: string;
  case_id?: string;
  user_question_raw: string;
  context: Record<string, unknown>;
  request_payload_redacted: Record<string, unknown>;
  raw_model_response: unknown;
  parsed_normalized_json: unknown;
  validation_result: {
    passed: boolean;
    errors: string[];
  };
  route_hint_summary?: unknown;
  route_hint: string | null;
  confidence: string | null;
  usage: {
    input_tokens: number;
    output_tokens: number;
    total_tokens: number;
  };
  latency_ms: number;
  expected_route?: string;
  eval_label?: string;
  eval_mode?: string;
  request_count_for_case: number;
}

export interface HistoryListItem {
  trace_id: string;
  timestamp: string;
  model: string;
  question_short: string;
  confidence: string | null;
  validation_passed: boolean;
  route_hint: string | null;
  save_status: "saved";
}

function redactSecrets(payload: Record<string, unknown>): Record<string, unknown> {
  const output = { ...payload };
  delete output.apiKey;
  return output;
}

export function saveTrace(record: TraceRecord): void {
  ensureDir(TRACES_DIR);
  const target = path.resolve(TRACES_DIR, `${record.trace_id}.json`);
  writeJsonFile(target, record);
}

export function listTraces(limit = 100): HistoryListItem[] {
  ensureDir(TRACES_DIR);
  const files = fs
    .readdirSync(TRACES_DIR)
    .filter((item) => item.endsWith(".json"))
    .sort((a, b) => {
      const pa = path.resolve(TRACES_DIR, a);
      const pb = path.resolve(TRACES_DIR, b);
      return fs.statSync(pb).mtimeMs - fs.statSync(pa).mtimeMs;
    })
    .slice(0, limit);

  return files.map((fileName) => {
    const raw = fs.readFileSync(path.resolve(TRACES_DIR, fileName), "utf-8");
    const item = JSON.parse(raw) as TraceRecord;
    return {
      trace_id: item.trace_id,
      timestamp: item.timestamp,
      model: item.model,
      question_short: item.user_question_raw.slice(0, 110),
      confidence: item.confidence,
      validation_passed: item.validation_result.passed,
      route_hint: item.route_hint,
      save_status: "saved"
    };
  });
}

export function getTrace(traceId: string): TraceRecord | null {
  ensureDir(TRACES_DIR);
  const target = path.resolve(TRACES_DIR, `${traceId}.json`);
  if (!fs.existsSync(target)) {
    return null;
  }
  const raw = fs.readFileSync(target, "utf-8");
  return JSON.parse(raw) as TraceRecord;
}

export function savePreset(preset: PromptPreset): void {
  ensureDir(PRESETS_DIR);
  writeJsonFile(path.resolve(PRESETS_DIR, `${preset.id}.json`), preset);
}

export function listPresets(): PromptPreset[] {
  ensureDir(PRESETS_DIR);
  return fs
    .readdirSync(PRESETS_DIR)
    .filter((item) => item.endsWith(".json"))
    .map((fileName) => {
      const raw = fs.readFileSync(path.resolve(PRESETS_DIR, fileName), "utf-8");
      return JSON.parse(raw) as PromptPreset;
    })
    .sort((a, b) => b.updatedAt.localeCompare(a.updatedAt));
}

export function saveEvalCase(casePayload: Record<string, unknown>): string {
  ensureDir(EVAL_CASES_DIR);
  const id = String(casePayload.case_id ?? `NQ-${Date.now()}`);
  writeJsonFile(path.resolve(EVAL_CASES_DIR, `${id}.json`), casePayload);
  return id;
}

export function redactRequestPayload(payload: Record<string, unknown>): Record<string, unknown> {
  return redactSecrets(payload);
}
