/**
 * Detailed Request Logs DB Layer (#378)
 *
 * Legacy compatibility layer for detailed request logs.
 * New requests now store pipeline details inside unified call log artifacts.
 * This module remains available for reading historical request_detail_logs rows.
 */
import { v4 as uuidv4 } from "uuid";
import { getDbInstance } from "./core";
import { getSettings } from "./settings";
import { isNoLog } from "../compliance/noLog";
import {
  protectPayloadForLog,
  serializePayloadForStorage,
  parseStoredPayload,
} from "../logPayloads";
import { compactStructuredStreamPayload } from "@omniroute/open-sse/utils/streamPayloadCollector.ts";

export interface RequestDetailLog {
  id?: string;
  call_log_id?: string | null;
  timestamp?: string;
  client_request?: unknown | null;
  translated_request?: unknown | null;
  provider_response?: unknown | null;
  client_response?: unknown | null;
  provider?: string | null;
  model?: string | null;
  source_format?: string | null;
  target_format?: string | null;
  duration_ms?: number;
  api_key_id?: string | null;
  no_log?: boolean;
}

let requestDetailLogsTableExistsCache: boolean | undefined;

function requestDetailLogsTableExists(): boolean {
  if (requestDetailLogsTableExistsCache !== undefined) {
    return requestDetailLogsTableExistsCache;
  }

  const db = getDbInstance();
  const row = db
    .prepare("SELECT name FROM sqlite_master WHERE type = 'table' AND name = 'request_detail_logs'")
    .get() as { name?: string } | undefined;
  requestDetailLogsTableExistsCache = Boolean(row?.name);
  return requestDetailLogsTableExistsCache;
}

export function resetRequestDetailLogsTableExistsCache(): void {
  requestDetailLogsTableExistsCache = undefined;
}

/** Returns true if detailed logging is enabled in settings */
export async function isDetailedLoggingEnabled(): Promise<boolean> {
  try {
    const settings = await getSettings();
    const val = settings.call_log_pipeline_enabled;
    return val === true || val === "1" || val === "true";
  } catch {
    return false;
  }
}

/** Save a detailed log entry — caller must verify isDetailedLoggingEnabled() first */
export function saveRequestDetailLog(entry: RequestDetailLog): void {
  const noLogEnabled =
    Boolean(entry.no_log) || (entry.api_key_id ? isNoLog(entry.api_key_id) : false);
  if (noLogEnabled || !requestDetailLogsTableExists()) return;

  const db = getDbInstance();
  const id = entry.id ?? uuidv4();
  const timestamp = entry.timestamp ?? new Date().toISOString();
  const compactProviderResponse = compactStructuredStreamPayload(entry.provider_response);
  const compactClientResponse = compactStructuredStreamPayload(entry.client_response);

  db.prepare(
    `
    INSERT INTO request_detail_logs
      (id, call_log_id, timestamp, client_request, translated_request,
       provider_response, client_response, provider, model, source_format, target_format, duration_ms)
    VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
  `
  ).run(
    id,
    entry.call_log_id ?? null,
    timestamp,
    serializePayloadForStorage(protectPayloadForLog(entry.client_request)),
    serializePayloadForStorage(protectPayloadForLog(entry.translated_request)),
    serializePayloadForStorage(protectPayloadForLog(compactProviderResponse)),
    serializePayloadForStorage(protectPayloadForLog(compactClientResponse)),
    entry.provider ?? null,
    entry.model ?? null,
    entry.source_format ?? null,
    entry.target_format ?? null,
    entry.duration_ms ?? 0
  );
}

/** Fetch detailed logs (latest first) */
export function getRequestDetailLogs(limit = 50, offset = 0): RequestDetailLog[] {
  if (!requestDetailLogsTableExists()) return [];
  const db = getDbInstance();
  const rows = db
    .prepare(
      `
      SELECT * FROM request_detail_logs
      ORDER BY timestamp DESC
      LIMIT ? OFFSET ?
    `
    )
    .all(limit, offset) as Array<Record<string, unknown>>;

  return rows.map(mapDetailedLogRow);
}

/** Get a single detailed log by ID */
export function getRequestDetailLogById(id: string): RequestDetailLog | null {
  if (!requestDetailLogsTableExists()) return null;
  const db = getDbInstance();
  const row = db.prepare("SELECT * FROM request_detail_logs WHERE id = ?").get(id) as
    | Record<string, unknown>
    | undefined;
  return row ? mapDetailedLogRow(row) : null;
}

/** Get the most recent detailed log for a call log ID */
export function getRequestDetailLogByCallLogId(callLogId: string): RequestDetailLog | null {
  if (!requestDetailLogsTableExists()) return null;
  const db = getDbInstance();
  const row = db
    .prepare(
      `
      SELECT * FROM request_detail_logs
      WHERE call_log_id = ?
      ORDER BY timestamp DESC
      LIMIT 1
    `
    )
    .get(callLogId) as Record<string, unknown> | undefined;
  return row ? mapDetailedLogRow(row) : null;
}

/** Get total count of detailed logs */
export function getRequestDetailLogCount(): number {
  if (!requestDetailLogsTableExists()) return 0;
  const db = getDbInstance();
  const row = db.prepare("SELECT COUNT(*) as cnt FROM request_detail_logs").get() as {
    cnt: number;
  };
  return row?.cnt ?? 0;
}

function mapDetailedLogRow(row: Record<string, unknown>): RequestDetailLog {
  return {
    id: typeof row.id === "string" ? row.id : undefined,
    call_log_id: typeof row.call_log_id === "string" ? row.call_log_id : null,
    timestamp: typeof row.timestamp === "string" ? row.timestamp : undefined,
    client_request: parseStoredPayload(row.client_request),
    translated_request: parseStoredPayload(row.translated_request),
    provider_response: parseStoredPayload(row.provider_response),
    client_response: parseStoredPayload(row.client_response),
    provider: typeof row.provider === "string" ? row.provider : null,
    model: typeof row.model === "string" ? row.model : null,
    source_format: typeof row.source_format === "string" ? row.source_format : null,
    target_format: typeof row.target_format === "string" ? row.target_format : null,
    duration_ms: typeof row.duration_ms === "number" ? row.duration_ms : 0,
  };
}
