#!/usr/bin/env tsx
/**
 * Seed GooseFactory Database from MCP Command Center State
 *
 * Reads the current MCP pipeline state from mcpengine-repo
 * and converts it into GooseFactory pipeline records.
 *
 * Usage: npx tsx scripts/seed-from-factory.ts
 */

import { readFileSync, existsSync } from "node:fs";
import { resolve } from "node:path";

// ─── Configuration ───

const STATE_PATHS = [
  resolve(import.meta.dirname ?? ".", "../../../mcpengine-repo/infra/command-center/state.json"),
  resolve(import.meta.dirname ?? ".", "../../mcpengine-repo/infra/command-center/state.json"),
  resolve(import.meta.dirname ?? ".", "../../../mcp-command-center/state.json"),
];

const DB_URL = process.env.DATABASE_URL || "postgresql://goosefactory:goosefactory_dev@localhost:5432/goosefactory";

// ─── Types for the old state format ───

interface OldState {
  version: number;
  phases: Array<{ id: number; name: string; stages: number[] }>;
  stages: Array<{ id: number; name: string; phase: number }>;
  mcps: Array<{
    id: number;
    name: string;
    slug?: string;
    stage: number;
    priority?: string;
    status?: string;
    assignee?: string;
    tags?: string[];
    metadata?: Record<string, unknown>;
    startedAt?: string;
    completedAt?: string;
    stageHistory?: Array<{ stage: number; enteredAt: string; completedAt?: string }>;
  }>;
  decisions: {
    pending: unknown[];
    history: unknown[];
  };
}

// ─── Stage Mapping (old stage IDs → GooseFactory stages) ───

function mapStageToFactory(stageId: number, stages: OldState["stages"]): string {
  const stage = stages.find((s) => s.id === stageId);
  if (!stage) return "intake";

  const name = stage.name.toLowerCase();

  // Map old phases/stages to GooseFactory pipeline stages
  if (name.includes("identified") || name.includes("research") || name.includes("architecture")) return "intake";
  if (name.includes("scaffold") || name.includes("bootstrap") || name.includes("init")) return "scaffolding";
  if (name.includes("build") || name.includes("implement") || name.includes("develop") || name.includes("code")) return "building";
  if (name.includes("test") || name.includes("qa") || name.includes("validation")) return "testing";
  if (name.includes("review") || name.includes("audit")) return "review";
  if (name.includes("staging") || name.includes("deploy") || name.includes("pre-prod")) return "staging";
  if (name.includes("production") || name.includes("live") || name.includes("release")) return "production";
  if (name.includes("publish") || name.includes("marketplace") || name.includes("launched")) return "published";

  // Phase-based fallback
  const phaseStage = stages.find((s) => s.id === stageId);
  if (phaseStage) {
    const phaseId = phaseStage.phase;
    if (phaseId <= 1) return "intake";
    if (phaseId === 2) return "building";
    if (phaseId === 3) return "testing";
    if (phaseId === 4) return "review";
    if (phaseId === 5) return "staging";
    if (phaseId === 6) return "production";
    if (phaseId >= 7) return "published";
  }

  return "intake";
}

function mapPriority(priority?: string): string {
  if (!priority) return "medium";
  const p = priority.toLowerCase();
  if (p === "critical" || p === "urgent") return "critical";
  if (p === "high") return "high";
  if (p === "low") return "low";
  return "medium";
}

function slugify(name: string): string {
  return name
    .toLowerCase()
    .replace(/[^a-z0-9]+/g, "-")
    .replace(/^-|-$/g, "");
}

// ─── Main ───

async function main() {
  console.log("🌱 GooseFactory Seed Script\n");

  // Find state file
  let statePath: string | null = null;
  for (const p of STATE_PATHS) {
    if (existsSync(p)) {
      statePath = p;
      break;
    }
  }

  if (!statePath) {
    console.log("⚠️  No MCP command center state.json found at:");
    STATE_PATHS.forEach((p) => console.log(`   ${p}`));
    console.log("\n   Skipping seed. You can seed manually later.");
    process.exit(0);
  }

  console.log(`📄 Reading state from: ${statePath}`);
  const raw = readFileSync(statePath, "utf-8");
  const state: OldState = JSON.parse(raw);

  console.log(`   Found ${state.mcps.length} MCP servers`);
  console.log(`   Found ${state.stages.length} stages across ${state.phases.length} phases\n`);

  // Convert MCPs to GooseFactory pipelines
  const pipelines = state.mcps.map((mcp) => {
    const factoryStage = mapStageToFactory(mcp.stage, state.stages);
    const slug = mcp.slug || slugify(mcp.name);

    // Determine status based on stage
    let status = "active";
    if (factoryStage === "published") status = "completed";
    if (mcp.status === "paused" || mcp.status === "blocked") status = "paused";
    if (mcp.status === "failed") status = "failed";

    return {
      name: mcp.name,
      slug,
      template: "mcp-server-standard",
      platform: slug.replace(/-mcp.*/, ""),
      currentStage: factoryStage,
      status,
      priority: mapPriority(mcp.priority),
      config: mcp.metadata || {},
      metadata: {
        importedFrom: "mcp-command-center",
        originalStageId: mcp.stage,
        originalId: mcp.id,
        tags: mcp.tags || [],
      },
      startedAt: mcp.startedAt || new Date().toISOString(),
      completedAt: mcp.completedAt || null,
    };
  });

  // Generate SQL inserts
  console.log("📝 Generated pipeline records:\n");

  const sqlStatements: string[] = [];

  for (const p of pipelines) {
    const sql = `INSERT INTO pipelines (name, slug, template, platform, current_stage, status, priority, config, metadata, started_at, completed_at)
VALUES ('${p.name.replace(/'/g, "''")}', '${p.slug.replace(/'/g, "''")}', '${p.template}', '${p.platform.replace(/'/g, "''")}', '${p.currentStage}', '${p.status}', '${p.priority}', '${JSON.stringify(p.config).replace(/'/g, "''")}', '${JSON.stringify(p.metadata).replace(/'/g, "''")}', '${p.startedAt}', ${p.completedAt ? `'${p.completedAt}'` : "NULL"})
ON CONFLICT (slug) DO UPDATE SET
  current_stage = EXCLUDED.current_stage,
  status = EXCLUDED.status,
  priority = EXCLUDED.priority,
  metadata = EXCLUDED.metadata,
  updated_at = NOW();`;

    sqlStatements.push(sql);
    console.log(`  📦 ${p.name} → ${p.currentStage} (${p.status})`);
  }

  // Write SQL file for manual import
  const sqlPath = resolve(import.meta.dirname ?? ".", "../infra/db/seed/seed-from-factory.sql");
  const sqlDir = resolve(import.meta.dirname ?? ".", "../infra/db/seed");

  const { mkdirSync, writeFileSync } = await import("node:fs");
  mkdirSync(sqlDir, { recursive: true });
  writeFileSync(sqlPath, `-- GooseFactory Seed Data\n-- Generated from MCP Command Center state.json\n-- Generated at: ${new Date().toISOString()}\n\n${sqlStatements.join("\n\n")}\n`);

  console.log(`\n✅ SQL seed file written to: ${sqlPath}`);
  console.log(`   Total pipelines: ${pipelines.length}`);

  // Try to execute against database
  try {
    // Dynamic import to avoid hard dependency on postgres
    const { default: postgres } = await import("postgres");
    const sql = postgres(DB_URL);

    console.log("\n🔌 Connecting to database...");
    
    for (const stmt of sqlStatements) {
      await sql.unsafe(stmt);
    }

    console.log(`✅ Seeded ${pipelines.length} pipelines into database`);
    await sql.end();
  } catch (err) {
    const error = err as Error;
    if (error.message?.includes("Cannot find module") || error.message?.includes("connect")) {
      console.log("\n⚠️  Could not connect to database — SQL file saved for manual import:");
      console.log(`   psql "$DATABASE_URL" < ${sqlPath}`);
    } else {
      console.error("\n⚠️  Database seed error:", error.message);
      console.log(`   SQL file saved for manual import: ${sqlPath}`);
    }
  }
}

main().catch((err) => {
  console.error("Fatal error:", err);
  process.exit(1);
});
