/**
 * Spec Validation Script
 *
 * Cross-checks enriched data against optical physics rules:
 * - 850nm MUST be MMF (not SMF)
 * - 1310nm/1550nm MUST be SMF (not MMF)
 * - Copper transceivers MUST NOT have optical wavelengths
 * - DAC/AOC reach must be < 100m (DAC) / < 300m (AOC)
 * - Power consumption must be plausible for form factor
 * - Connector must match fiber type (MPO for parallel, LC for duplex)
 */
import { config } from "dotenv";
import { join } from "path";
import { Pool } from "pg";

config({ path: join(__dirname, "..", ".env") });

const pool = new Pool({
  host: process.env.POSTGRES_HOST || "localhost",
  port: parseInt(process.env.POSTGRES_PORT || "5433"),
  database: process.env.POSTGRES_DB || "transceiver_db",
  user: process.env.POSTGRES_USER || "tip",
  password: process.env.POSTGRES_PASSWORD || "***REDACTED***",
  max: 3,
});

interface ValidationError {
  id: string;
  slug: string;
  field: string;
  value: string;
  rule: string;
  severity: "error" | "warning";
}

async function main() {
  console.log("Running spec validation...\n");

  const result = await pool.query(`
    SELECT id, slug, form_factor, speed_gbps, reach_label, reach_meters,
           fiber_type, connector, wavelengths, power_consumption_w, category
    FROM transceivers
    WHERE data_confidence = 'enriched_estimated' OR data_confidence = 'unknown'
  `);

  console.log(`Validating ${result.rows.length} enriched/unknown products\n`);

  const errors: ValidationError[] = [];

  for (const row of result.rows) {
    const ft = row.fiber_type || "";
    const conn = row.connector || "";
    const wl = row.wavelengths || "";
    const reach = row.reach_meters || 0;
    const speed = parseFloat(row.speed_gbps || 0);
    const power = row.power_consumption_w ? parseFloat(row.power_consumption_w) : null;
    const ff = row.form_factor || "";

    // Rule 1: 850nm wavelength MUST be MMF (not SMF)
    if (wl.includes("850") && ft === "SMF") {
      errors.push({ id: row.id, slug: row.slug, field: "fiber_type", value: ft,
        rule: "850nm wavelength requires MMF, not SMF", severity: "error" });
    }

    // Rule 2: 1310nm/1550nm wavelength MUST be SMF (not MMF, unless SWDM)
    if ((wl.includes("1310") || wl.includes("1550")) && ft === "MMF" && !wl.includes("SWDM")) {
      errors.push({ id: row.id, slug: row.slug, field: "fiber_type", value: ft,
        rule: "1310/1550nm requires SMF, not MMF", severity: "error" });
    }

    // Rule 3: Copper must not have optical wavelengths
    if (ft === "Copper" && wl !== "N/A" && wl !== "" && !wl.includes("N/A")) {
      errors.push({ id: row.id, slug: row.slug, field: "wavelengths", value: wl,
        rule: "Copper transceiver should have wavelengths=N/A", severity: "warning" });
    }

    // Rule 4: DAC reach must be <= 7m (passive) or <= 30m (active)
    if (conn === "DAC" && reach > 30) {
      errors.push({ id: row.id, slug: row.slug, field: "reach_meters", value: String(reach),
        rule: "DAC reach > 30m is implausible (max ~7m passive, ~30m active)", severity: "warning" });
    }

    // Rule 5: AOC reach should be <= 300m
    if ((conn === "AOC" || ft === "AOC") && reach > 300) {
      errors.push({ id: row.id, slug: row.slug, field: "reach_meters", value: String(reach),
        rule: "AOC reach > 300m is implausible", severity: "warning" });
    }

    // Rule 6: Power consumption plausibility
    if (power !== null) {
      const maxPower: Record<string, number> = {
        "SFP": 1.5, "SFP+": 2.0, "SFP28": 2.0, "SFP56": 2.5,
        "QSFP+": 4.0, "QSFP28": 5.0, "QSFP56": 7.0,
        "QSFP-DD": 18.0, "OSFP": 22.0, "QSFP-DD800": 25.0,
        "CFP2": 12.0, "CFP2-DCO": 25.0, "XFP": 5.0,
      };
      const max = maxPower[ff];
      if (max && power > max * 1.5) {
        errors.push({ id: row.id, slug: row.slug, field: "power_consumption_w", value: String(power),
          rule: `Power ${power}W exceeds plausible max ${max}W for ${ff}`, severity: "error" });
      }
    }

    // Rule 7: MPO connector should be for parallel optics (40G+, SR4/DR4/PSM4)
    if (conn.startsWith("MPO") && speed < 40 && ft !== "SMF") {
      errors.push({ id: row.id, slug: row.slug, field: "connector", value: conn,
        rule: "MPO connector unusual for <40G non-SMF", severity: "warning" });
    }

    // Rule 8: LC connector for SMF is standard, but QSFP+ SR4 should be MPO
    if (conn === "LC" && ft === "MMF" && speed >= 40 && row.reach_label?.includes("SR")) {
      errors.push({ id: row.id, slug: row.slug, field: "connector", value: conn,
        rule: "SR4 on MMF at 40G+ typically uses MPO, not LC", severity: "warning" });
    }
  }

  // Print results
  const errs = errors.filter(e => e.severity === "error");
  const warns = errors.filter(e => e.severity === "warning");

  console.log(`\nValidation Results:`);
  console.log(`  Errors:   ${errs.length}`);
  console.log(`  Warnings: ${warns.length}`);
  console.log(`  Total:    ${errors.length}`);

  if (errs.length > 0) {
    console.log(`\n=== ERRORS (need fixing) ===`);
    for (const e of errs.slice(0, 30)) {
      console.log(`  ${e.slug}: ${e.field}="${e.value}" — ${e.rule}`);
    }
  }

  if (warns.length > 0) {
    console.log(`\n=== WARNINGS (review) ===`);
    for (const w of warns.slice(0, 20)) {
      console.log(`  ${w.slug}: ${w.field}="${w.value}" — ${w.rule}`);
    }
  }

  // Auto-fix clear errors
  let fixed = 0;
  for (const e of errs) {
    if (e.rule.includes("850nm wavelength requires MMF")) {
      await pool.query(`UPDATE transceivers SET fiber_type = 'MMF' WHERE id = $1`, [e.id]);
      fixed++;
    }
    if (e.rule.includes("1310/1550nm requires SMF")) {
      await pool.query(`UPDATE transceivers SET fiber_type = 'SMF' WHERE id = $1`, [e.id]);
      fixed++;
    }
  }

  if (fixed > 0) console.log(`\nAuto-fixed ${fixed} errors`);

  await pool.end();
}

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