#!/usr/bin/env bun
/**
 * Agent Pipeline Validator
 *
 * Validates pipeline manifest and agent definitions
 * Usage: ./validate-pipeline.ts [pipeline-name]
 */

import { readFileSync, existsSync } from 'fs';
import { join } from 'path';

interface PipelineManifest {
  name: string;
  stages: Array<{ name: string; description: string }>;
  dataFormat?: string;
}

interface AgentDefinition {
  name: string;
  description: string;
  model?: string;
}

function parseFrontmatter(content: string): { frontmatter: any; content: string } {
  const match = content.match(/^---\n([\s\S]+?)\n---\n([\s\S]*)$/);
  if (!match) {
    return { frontmatter: {}, content };
  }

  const frontmatter: any = {};
  const lines = match[1].split('\n');
  for (const line of lines) {
    const [key, ...valueParts] = line.split(':');
    if (key && valueParts.length > 0) {
      const value = valueParts.join(':').trim();
      frontmatter[key.trim()] = value;
    }
  }

  return { frontmatter, content: match[2] };
}

function validateAgentFile(agentPath: string): { valid: boolean; errors: string[] } {
  const errors: string[] = [];

  if (!existsSync(agentPath)) {
    return { valid: false, errors: [`Agent file not found: ${agentPath}`] };
  }

  const content = readFileSync(agentPath, 'utf-8');
  const { frontmatter } = parseFrontmatter(content);

  // Check required fields
  if (!frontmatter.name) {
    errors.push(`Missing 'name' in frontmatter`);
  }

  if (!frontmatter.description) {
    errors.push(`Missing 'description' in frontmatter`);
  }

  // Check for output markers
  const markerPattern = /<<<(\w+)>>>/g;
  const markers = content.match(markerPattern);
  if (!markers || markers.length < 2) {
    errors.push(`Missing output markers (expected <<<stage>>>...<<<end-stage>>>)`);
  }

  return { valid: errors.length === 0, errors };
}

function validatePipeline(pipelineName: string): void {
  const basePath = join(process.cwd(), '.claude', 'agents', pipelineName);
  const manifestPath = join(basePath, 'pipeline.md');

  console.log(`\n🔍 Validating pipeline: ${pipelineName}\n`);

  // Check if pipeline directory exists
  if (!existsSync(basePath)) {
    console.error(`❌ Pipeline directory not found: ${basePath}`);
    process.exit(1);
  }

  // Load and validate manifest
  let stages: string[] = [];
  if (existsSync(manifestPath)) {
    const manifestContent = readFileSync(manifestPath, 'utf-8');
    const { frontmatter } = parseFrontmatter(manifestContent);
    stages = frontmatter.stages?.map((s: any) => typeof s === 'string' ? s : s.name) || [];
  }

  // If no manifest, auto-detect agents
  if (stages.length === 0) {
    const { readdirSync } = require('fs');
    const files = readdirSync(basePath).filter((f: string) => f.endsWith('.md') && f !== 'pipeline.md');
    stages = files.map((f: string) => f.replace('.md', ''));
  }

  console.log(`📋 Stages: ${stages.join(' → ')}\n`);

  // Validate each agent
  let hasErrors = false;
  for (const stage of stages) {
    const agentPath = join(basePath, `${stage}.md`);
    const { valid, errors } = validateAgentFile(agentPath);

    if (valid) {
      console.log(`  ✅ ${stage}`);
    } else {
      console.log(`  ❌ ${stage}`);
      for (const error of errors) {
        console.log(`     ${error}`);
      }
      hasErrors = true;
    }
  }

  // Check for scripts
  const scriptsPath = join(process.cwd(), 'scripts', `run-${pipelineName}.ts`);
  if (existsSync(scriptsPath)) {
    console.log(`\n  ✅ Pipeline script: ${scriptsPath}`);
  } else {
    console.log(`\n  ⚠️  Missing pipeline script: ${scriptsPath}`);
    console.log(`     Create this script to orchestrate the agents.`);
  }

  console.log('');

  if (hasErrors) {
    console.log('❌ Pipeline validation failed\n');
    process.exit(1);
  } else {
    console.log('✅ Pipeline validation passed!\n');
  }
}

// Main
const pipelineName = process.argv[2];

if (!pipelineName) {
  console.log('Usage: validate-pipeline.ts <pipeline-name>');
  console.log('Example: validate-pipeline.ts ai-news-tweet');
  process.exit(1);
}

validatePipeline(pipelineName);
