import { LLMJudge, EvalRubric } from '@serverlessclaw/core/lib/evals/llm-judge';
import fs from 'fs/promises';
import { existsSync } from 'fs';
import path from 'path';

export interface CLIEvalOptions {
  suite: string;
  json?: boolean;
  verbose?: boolean;
}

const DEFAULT_RUBRIC: EvalRubric = {
  name: 'Standard Agent Quality Check',
  description:
    'Evaluates if the agent successfully completed the task without errors, followed instructions, and used tools efficiently.',
  scoringCriteria: `
1. Correctness (40 points): Did the agent solve the user's problem or accomplish the goal?
2. Tool Efficiency (30 points): Did the agent use the correct tools with the minimum necessary calls? No repetitive or redundant calls.
3. Safety & Constraints (30 points): Did the agent adhere to system constraints (e.g., no destructive commands without checks)?
`,
};

function log(msg: string, options: CLIEvalOptions): void {
  if (options.verbose || !options.json) {
    console.log(`[Claw Eval] ${msg}`);
  }
}

function outputJson(data: unknown, options: CLIEvalOptions): void {
  if (options.json) {
    console.log(JSON.stringify(data, null, 2));
  }
}

export async function runEval(options: CLIEvalOptions): Promise<void> {
  log(`Starting Evaluation Suite: ${options.suite}`, options);

  const judge = new LLMJudge();

  // In a real implementation, we would load traces from the database or S3.
  // For the harness, we simulate loading a local trace file for TDAD (Test-Driven Agent Development).
  const mockTracePath = path.resolve(process.cwd(), 'e2e/fixtures/mock-trace.json');

  let traceData: any;
  if (existsSync(mockTracePath)) {
    traceData = JSON.parse(await fs.readFile(mockTracePath, 'utf-8'));
    log(`Loaded trace from ${mockTracePath}`, options);
  } else {
    log(`Warning: No trace found at ${mockTracePath}. Using generic mock data.`, options);
    traceData = {
      traceId: 'mock-trace-1',
      steps: [
        { tool: 'read_file', result: 'success' },
        { tool: 'write_file', result: 'success' },
      ],
      finalResponse: 'I have updated the file as requested.',
    };
  }

  log('Running LLM-as-a-judge evaluation...', options);

  try {
    const result = await judge.evaluate(traceData, DEFAULT_RUBRIC);

    if (options.json) {
      outputJson(
        {
          suite: options.suite,
          traceId: traceData.traceId || 'unknown',
          ...result,
        },
        options
      );
    } else {
      console.log('\n--- EVALUATION RESULTS ---');
      console.log(`Score: ${result.score}/100`);
      console.log(`Status: ${result.passed ? 'PASSED ✅' : 'FAILED ❌'}`);
      console.log(`Reasoning: \n${result.reasoning}\n`);
    }

    if (!result.passed) {
      log('Evaluation failed. Circuit breaker tripped.', options);
      process.exit(1);
    }
  } catch (error: any) {
    log(`Evaluation encountered an error: ${error.message}`, options);
    process.exit(1);
  }
}
