/**
 * traceTypes.ts
 *
 * TRACE (Tool-Routed Architecture for Controlled Execution)
 * Shared types for the Verifiable Orchestrator pattern.
 *
 * Key principle: LLM = Orchestrator (planning), NOT Analyst (data generation).
 * All computation is pushed into deterministic tools. The LLM only sees metadata.
 *
 * Three distinct outputs:
 * 1. Raw Data/Artifact — untouched by LLM, produced by deterministic tools
 * 2. Audit Log — code-generated, deterministic trace of steps taken
 * 3. Analysis — LLM-generated, clearly labeled as non-deterministic
 */

// ============================================================================
// TRACE Decision Loop Choices
// ============================================================================

/**
 * Choice 1: Gather Information (Read-Only)
 * The LLM requests to "see" data samples, schema info, or call research tools.
 * Non-destructive. Result is returned to the LLM to build context.
 * Addresses Risk 3: Lack of Native Domain Concept Understanding.
 */
export interface TraceGatherInfo {
  type: "gather_info";
  tool: string;
  params: Record<string, unknown>;
  description: string;
}

/**
 * Choice 2: Execute Data Operation (Deterministic Transformation)
 * The LLM selects a tool (filter, sort, join, aggregate, etc.).
 * Tool executes deterministically, stores results in immutable Data Store,
 * and returns ONLY metadata (row counts, summaries) to the LLM.
 * Addresses Risk 2 (Probabilistic→Deterministic) and Risk 4 (Cost/Latency).
 */
export interface TraceExecuteDataOp {
  type: "execute_data_op";
  tool: string;
  params: Record<string, unknown>;
  viewName: string;
  description: string;
}

/**
 * Choice 3: Execute Output Tool
 * The LLM selects an output-generating tool (chart, CSV, export).
 * This tool reads data from the data store to produce a deliverable.
 */
export interface TraceExecuteOutput {
  type: "execute_output";
  tool: string;
  params: Record<string, unknown>;
  description: string;
}

/**
 * Choice 4: Finalize (Done)
 * The data that best addresses the user's query has been generated.
 * No more tools/actions are required.
 */
export interface TraceFinalize {
  type: "finalize";
  finalViewName: string;
  description: string;
}

export type TraceChoice =
  | TraceGatherInfo
  | TraceExecuteDataOp
  | TraceExecuteOutput
  | TraceFinalize;

// ============================================================================
// Audit Log Types (Deterministic, Code-Generated)
// ============================================================================

/**
 * A single audit log entry — generated by CODE, not by the LLM.
 * This is the core trust mechanism: users can read exactly what tools did.
 */
export interface TraceAuditEntry {
  seq: number;
  timestamp: number;
  choiceType: TraceChoice["type"];
  toolName: string;
  toolParams: Record<string, unknown>;
  description: string;
  metadata: TraceMetadataFeedback;
  correction?: TraceSelfCorrection;
}

/**
 * Metadata feedback from a tool execution.
 * This is what the LLM receives — structured summaries, NOT raw data.
 */
export interface TraceMetadataFeedback {
  rowCount?: number;
  columnCount?: number;
  uniqueValues?: Record<string, number>;
  charCount?: number;
  wordCount?: number;
  keyTopics?: string[];
  errorMessage?: string;
  durationMs: number;
  success: boolean;
}

/**
 * Self-correction tracking (FB → META pattern).
 * When intended state !== actual state, the orchestrator detects a mismatch
 * and triggers a gather_info step to resolve.
 */
export interface TraceSelfCorrection {
  intendedState: string;
  actualState: string;
  correctionApplied: boolean;
  correctionDescription?: string;
}

// ============================================================================
// Data Store Types
// ============================================================================

/**
 * An immutable data view in the TRACE data store.
 * Data is stored outside the LLM context window.
 * The LLM only sees the metadata summary.
 */
export interface TraceDataView {
  viewName: string;
  createdBy: string;
  createdAt: number;
  rowCount: number;
  columns: string[];
  dataSummary: string;
}

// ============================================================================
// Final TRACE Output
// ============================================================================

/**
 * The three distinct outputs produced by the TRACE framework.
 * Trust comes from the clear separation:
 * - rawData: deterministic, untouched by LLM
 * - auditLog: code-generated, NOT LLM-generated
 * - analysis: LLM-generated, CLEARLY LABELED as non-deterministic
 */
export interface TraceOutput {
  executionId: string;
  executionType: "swarm" | "tree" | "chat" | "forecast_refresh" | "linkedin_post";
  rawDataViewName: string;
  auditLog: TraceAuditEntry[];
  analysis?: string;
  analysisIsNonDeterministic: true;
  confidence: number;
  totalDurationMs: number;
  totalSteps: number;
  selfCorrections: number;
}

// ============================================================================
// Deterministic Metadata Extraction
// ============================================================================

/**
 * Extract structured metadata from text WITHOUT using the LLM.
 * This ensures the LLM never sees raw agent output — only structured metadata.
 *
 * Uses regex and simple NLP, NOT probabilistic models.
 */
export function extractMetadataSummary(text: string): TraceMetadataFeedback {
  const words = text.split(/\s+/).filter(Boolean);
  const sentences = text.split(/[.!?]+/).filter(s => s.trim().length > 0);

  // Extract top n-grams deterministically
  const bigramCounts: Record<string, number> = {};
  for (let i = 0; i < words.length - 1; i++) {
    const bigram = `${words[i].toLowerCase()} ${words[i + 1].toLowerCase()}`;
    bigramCounts[bigram] = (bigramCounts[bigram] || 0) + 1;
  }
  const topBigrams = Object.entries(bigramCounts)
    .sort((a, b) => b[1] - a[1])
    .slice(0, 5)
    .map(([bigram]) => bigram);

  // Detect named entities via regex (basic)
  const entityPatterns = [
    /\b[A-Z][a-z]+(?:\s[A-Z][a-z]+)+\b/g, // Multi-word proper nouns
    /\b[A-Z]{2,5}\b/g,                      // Acronyms (2-5 uppercase letters)
    /\$[\d,.]+[BMKbmk]?\b/g,                // Dollar amounts
    /\b\d{1,2}[/-]\d{1,2}[/-]\d{2,4}\b/g,   // Dates
  ];

  const entities: string[] = [];
  for (const pattern of entityPatterns) {
    const matches = text.match(pattern);
    if (matches) {
      entities.push(...matches.slice(0, 5));
    }
  }

  return {
    charCount: text.length,
    wordCount: words.length,
    rowCount: sentences.length,
    keyTopics: [...new Set([...topBigrams, ...entities])].slice(0, 10),
    durationMs: 0,
    success: true,
  };
}

/**
 * Generate a human-readable metadata summary string for display.
 * This is used in the audit log to describe what a tool returned.
 */
export function formatMetadataSummary(meta: TraceMetadataFeedback): string {
  const parts: string[] = [];
  if (meta.rowCount !== undefined) parts.push(`${meta.rowCount} rows`);
  if (meta.columnCount !== undefined) parts.push(`${meta.columnCount} columns`);
  if (meta.charCount !== undefined) parts.push(`${meta.charCount} chars`);
  if (meta.wordCount !== undefined) parts.push(`${meta.wordCount} words`);
  if (meta.keyTopics && meta.keyTopics.length > 0) {
    parts.push(`topics: [${meta.keyTopics.slice(0, 3).join(", ")}]`);
  }
  if (meta.errorMessage) parts.push(`error: ${meta.errorMessage}`);
  if (!meta.success) parts.push("FAILED");
  return parts.join(", ") || "no metadata";
}
