/**
 * Hype Cycle API routes
 *
 * GET /api/hype-cycle              — All technologies with current phase
 * GET /api/hype-cycle/enriched     — All technologies with data-driven metrics
 * GET /api/hype-cycle/lifecycle    — Revenue lifecycle predictions for all speeds
 * GET /api/hype-cycle/regional/:tech — Regional adoption model for a technology
 * GET /api/hype-cycle/:tech        — Specific technology with 5-year forecast
 */
import { Router, Request, Response } from "express";
import {
  computeAllHypeCycles,
  computeHypeCycle,
  findTechnology,
  TECH_GENERATIONS,
  SPECIAL_TECHS,
} from "../hype-cycle/norton-bass";
import {
  getDataDrivenOverrides,
  getSpeedClassMetrics,
  computeRevenueLifecycle,
  computeRegionalAdoption,
} from "../hype-cycle/data-enrichment";

export const hypeCycleRouter = Router();

const q = (p: string, req: Request): string | undefined =>
  req.query[p] ? String(req.query[p]) : undefined;

// GET /api/hype-cycle — All technologies (model-only, fast)
hypeCycleRouter.get("/", (_req: Request, res: Response) => {
  const yearParam = q("year", _req);
  const year = yearParam ? parseInt(yearParam) : new Date().getFullYear();

  const results = computeAllHypeCycles(year);
  const sorted = [...results].sort((a, b) => a.positionPct - b.positionPct);

  res.json({
    success: true,
    year,
    model: "Norton-Bass Multigenerational Diffusion",
    technologies: sorted.map((r) => ({
      technology: r.technology,
      phase: r.phaseLabel,
      positionPct: r.positionPct,
      adoptionPct: r.adoptionPct,
      compositeScore: r.compositeScore,
      peakYear: r.forecast.peakShipmentYear,
      yearsToPlateauFromNow: r.forecast.yearsToPlateauFromNow,
    })),
  });
});

// GET /api/hype-cycle/enriched — Data-driven enrichment from scraped data
hypeCycleRouter.get("/enriched", async (_req: Request, res: Response) => {
  try {
    const yearParam = q("year", _req);
    const year = yearParam ? parseInt(yearParam) : new Date().getFullYear();

    const overridesMap = await getDataDrivenOverrides();
    const allTechs = [...TECH_GENERATIONS, ...SPECIAL_TECHS];

    const results = allTechs.map((tech) => {
      const overrides = overridesMap.get(tech.speedGbps);
      return computeHypeCycle(tech, year, overrides);
    });

    const sorted = [...results].sort((a, b) => a.positionPct - b.positionPct);

    // Also include raw metrics for transparency
    const speedMetrics = await getSpeedClassMetrics();

    res.json({
      success: true,
      year,
      model: "Norton-Bass + Data-Driven Enrichment",
      dataSource: {
        totalTransceivers: speedMetrics.reduce((s, m) => s + m.skuCount, 0),
        totalPricePoints: speedMetrics.reduce((s, m) => s + m.priceCount, 0),
        speedClasses: speedMetrics.length,
      },
      technologies: sorted.map((r) => ({
        technology: r.technology,
        phase: r.phaseLabel,
        positionPct: r.positionPct,
        adoptionPct: r.adoptionPct,
        compositeScore: r.compositeScore,
        peakYear: r.forecast.peakShipmentYear,
        yearsToPlateauFromNow: r.forecast.yearsToPlateauFromNow,
        metrics: r.metrics,
        fiveYearForecast: r.forecast.fiveYearProjection,
      })),
      rawSpeedMetrics: speedMetrics.map((m) => ({
        speedGbps: m.speedGbps,
        vendorCount: m.vendorCount,
        skuCount: m.skuCount,
        avgPrice: m.avgPrice ? Math.round(m.avgPrice * 100) / 100 : null,
        minPrice: m.minPrice ? Math.round(m.minPrice * 100) / 100 : null,
        maxPrice: m.maxPrice ? Math.round(m.maxPrice * 100) / 100 : null,
        formFactors: m.formFactors,
        reachVariants: m.reachVariants,
      })),
    });
  } catch (err) {
    console.error("Enriched hype cycle error:", err);
    res.status(500).json({ success: false, error: "Failed to compute enriched hype cycle" });
  }
});

// GET /api/hype-cycle/lifecycle — Revenue lifecycle predictions
hypeCycleRouter.get("/lifecycle", async (_req: Request, res: Response) => {
  try {
    const currentYear = new Date().getFullYear();
    const speedMetrics = await getSpeedClassMetrics();
    const priceMap = new Map(speedMetrics.map((m) => [m.speedGbps, m.avgPrice]));

    const allTechs = [...TECH_GENERATIONS, ...SPECIAL_TECHS];
    const lifecycles = allTechs.map((tech) =>
      computeRevenueLifecycle(
        tech.speedGbps,
        tech.name,
        tech.introYear,
        tech.peakYear,
        currentYear,
        priceMap.get(tech.speedGbps),
      )
    );

    // Sort by revenue index (highest current revenue first)
    const sorted = [...lifecycles].sort((a, b) => b.revenueIndex - a.revenueIndex);

    res.json({
      success: true,
      currentYear,
      lifecycles: sorted,
    });
  } catch (err) {
    console.error("Lifecycle error:", err);
    res.status(500).json({ success: false, error: "Failed to compute lifecycles" });
  }
});

// GET /api/hype-cycle/regional/:tech — Regional adoption by technology
hypeCycleRouter.get("/regional/:tech", (req: Request, res: Response) => {
  const techQuery = String(req.params.tech);
  const currentYear = new Date().getFullYear();

  const tech = findTechnology(techQuery);
  if (!tech) {
    res.status(404).json({
      success: false,
      error: `Technology "${techQuery}" not found. Available: 1G, 10G, 25G, 40G, 100G, 400G, 800G, 1.6T, CPO, LPO, 400ZR`,
    });
    return;
  }

  const regions = computeRegionalAdoption(tech.peakYear, currentYear, tech.name);

  res.json({
    success: true,
    technology: tech.name,
    speedGbps: tech.speedGbps,
    globalPeakYear: tech.peakYear,
    regions,
  });
});

// ── MARKET SIGNAL COMPUTATION ───────────────────────────────────────────────
/** Technology → form-factor/speed mapping for cross-table signal aggregation */
const TECH_SIGNAL_MAP = [
  { label: "10G-SFP+",     speedGbps: 10,   formFactors: ["SFP+"],            speedLabel: "10G"  },
  { label: "100G-QSFP28",  speedGbps: 100,  formFactors: ["QSFP28"],          speedLabel: "100G" },
  { label: "400G-QSFP-DD", speedGbps: 400,  formFactors: ["QSFP-DD"],         speedLabel: "400G" },
  { label: "800G-OSFP",    speedGbps: 800,  formFactors: ["OSFP"],            speedLabel: "800G" },
  { label: "1.6T-OSFP",   speedGbps: 1600, formFactors: ["OSFP"],            speedLabel: "1.6T" },
  { label: "400G-ZR",      speedGbps: 400,  formFactors: ["SFP-DD", "CFP2"],  speedLabel: "400G" },
] as const;

type PhaseKey =
  | "plateau_productivity" | "slope_enlightenment" | "trough_disillusionment"
  | "peak_inflated_expectations" | "innovation_trigger";

function buildRecommendation(
  phase: PhaseKey,
  signalScore: number,
  capexYoyAvg: number,
  speedGbps: number,
): { label: string; color: string; detail: string } {
  const fast = speedGbps >= 400;
  const capexBoom = capexYoyAvg > 50;

  switch (phase) {
    case "plateau_productivity":
      if (fast && capexBoom)
        return { label: "🚀 Buy — AI Wave", color: "#16a34a", detail: "Commodity pricing + AI infrastructure demand surge. Stock up now." };
      if (signalScore >= 85)
        return { label: "✅ Hold — Stable", color: "#2563eb", detail: "Mature commodity market, stable long-term demand." };
      return { label: "📦 Hold", color: "#64748b", detail: "Commodity market. Price-driven. Order on demand." };
    case "slope_enlightenment":
      if (capexBoom)
        return { label: "🟢 Buy Now", color: "#16a34a", detail: "Growing mainstream adoption + hyperscaler capex boom. Window closing." };
      return { label: "🟡 Buy", color: "#ca8a04", detail: "Adoption curve steepening. Monitor pricing before large orders." };
    case "trough_disillusionment":
      if (signalScore > 50)
        return { label: "🔍 Buy Opportunity", color: "#7c3aed", detail: "Hype trough but demand signals emerging. Strategic buying window." };
      return { label: "⏳ Watch", color: "#94a3b8", detail: "Wait for demand confirmation before stocking." };
    case "peak_inflated_expectations":
      if (fast && capexBoom)
        return { label: "⚡ Caution / Buy", color: "#f97316", detail: "Hype peak but real hyperscaler demand. Buy selectively, not speculatively." };
      return { label: "⚠ Caution", color: "#ef4444", detail: "Peak hype. Verify real end-customer demand before building inventory." };
    case "innovation_trigger":
      return { label: "👁 Watch", color: "#94a3b8", detail: "Early stage — too early for volume commitments. Monitor for traction." };
    default:
      return { label: "📊 Monitor", color: "#64748b", detail: "Monitor signals." };
  }
}

// GET /api/hype-cycle/analysis — Bass-fitted results from DB (hype_cycle_analysis table)
hypeCycleRouter.get("/analysis", async (_req: Request, res: Response) => {
  try {
    const { pool } = await import("../db/client");
    const { rows } = await pool.query(`
      SELECT DISTINCT ON (technology)
        technology, computed_at,
        bass_p, bass_q, bass_m,
        t_peak_year, current_t,
        ROUND(current_share * 100, 1)       AS share_pct,
        ROUND(projected_share_1y * 100, 1)  AS share_1y_pct,
        ROUND(projected_share_3y * 100, 1)  AS share_3y_pct,
        hype_phase, hype_score,
        phase_since_year, years_to_next_phase,
        asp_current_usd, asp_decline_pct_3y,
        r_squared, data_points, notes
      FROM hype_cycle_analysis
      ORDER BY technology, computed_at DESC
    `);

    if (rows.length === 0) {
      res.json({ success: true, source: "db", data: [], message: "No analysis yet — run compute:hype-cycle job" });
      return;
    }

    res.json({ success: true, source: "db", computed_at: rows[0]?.computed_at, data: rows });
  } catch (err) {
    console.error("Hype cycle analysis DB error:", err);
    res.status(500).json({ success: false, error: "Failed to fetch analysis" });
  }
});

// GET /api/hype-cycle/:tech — Specific technology detail (must be last!)
// GET /api/hype-cycle/market-signals — data-driven per-technology market signal score + drivers + recommendation
hypeCycleRouter.get("/market-signals", async (_req: Request, res: Response) => {
  try {
    const yearParam = q("year", _req);
    const year = yearParam ? parseInt(yearParam) : new Date().getFullYear();
    const overridesMap = await getDataDrivenOverrides();
    const speedMetrics = await getSpeedClassMetrics();
    const metricsBySpeed = new Map(speedMetrics.map((m) => [m.speedGbps, m]));
    const maxSku = Math.max(1, ...speedMetrics.map((m) => m.skuCount));
    const allTechs = [...TECH_GENERATIONS, ...SPECIAL_TECHS];

    const technologies = allTechs.map((tech) => {
      const r = computeHypeCycle(tech, year, overridesMap.get(tech.speedGbps));
      const sm = metricsBySpeed.get(tech.speedGbps);
      const adoption = Math.max(0, Math.round(r.adoptionPct));
      const composite = Math.max(0, Math.round(r.compositeScore));
      const depth = sm ? Math.round(100 * Math.min(1, sm.skuCount / maxSku)) : 0;
      const marketSignalScore = Math.max(0, Math.min(100, Math.round(0.4 * adoption + 0.3 * composite + 0.3 * depth)));

      const drivers: string[] = [];
      drivers.push(adoption + "% modeled adoption");
      if (sm && sm.skuCount) drivers.push(sm.skuCount + " SKUs / " + sm.vendorCount + " vendors");
      if (sm && sm.avgPrice) drivers.push("avg $" + Math.round(sm.avgPrice));
      drivers.push("phase: " + r.phaseLabel);

      const phase = String(r.phaseLabel || "");
      let recommendation = { label: "Monitor", detail: "Insufficient market momentum — keep watching.", color: "#94a3b8" };
      if (/Plateau/i.test(phase)) recommendation = { label: "Commodity — negotiate", detail: "Mature, broad supply (" + (sm ? sm.vendorCount : 0) + " vendors). Push for price.", color: "#0ea5e9" };
      else if (/Slope/i.test(phase)) recommendation = { label: "Mainstream — buy", detail: "Mainstreaming with falling prices and rising supply.", color: "#16a34a" };
      else if (/Trough/i.test(phase)) recommendation = { label: "Maturing — opportunity", detail: "Past the hype; early mainstream pricing forming.", color: "#ca8a04" };
      else if (/Peak/i.test(phase)) recommendation = { label: "Hype peak — caution", detail: "Elevated expectations; supply and price still volatile.", color: "#f97316" };
      else if (/Innovation|Trigger/i.test(phase)) recommendation = { label: "Emerging — pilot", detail: "Early window; limited supply, premium pricing.", color: "#ca8a04" };

      return {
        technology: tech.name,
        phase: r.phaseLabel,
        marketSignalScore,
        adoptionPct: adoption,
        compositeScore: composite,
        skuCount: sm ? sm.skuCount : 0,
        vendorCount: sm ? sm.vendorCount : 0,
        avgPrice: sm && sm.avgPrice ? Math.round(sm.avgPrice * 100) / 100 : null,
        drivers,
        recommendation,
      };
    });

    technologies.sort((a, b) => b.marketSignalScore - a.marketSignalScore);

    const totalSkus = speedMetrics.reduce((acc, m) => acc + m.skuCount, 0);
    const totalVendors = speedMetrics.length ? Math.max(...speedMetrics.map((m) => m.vendorCount)) : 0;
    const avgSignal = technologies.length ? Math.round(technologies.reduce((acc, t) => acc + t.marketSignalScore, 0) / technologies.length) : 0;
    const globalContext = {
      totalSkus,
      totalVendors,
      avgMarketSignal: avgSignal,
      strongest: technologies.length ? technologies[0].technology : null,
      strongestScore: technologies.length ? technologies[0].marketSignalScore : null,
      generatedAt: new Date().toISOString(),
    };

    res.json({ success: true, year, technologies, globalContext });
  } catch (err) {
    console.error("market-signals error:", err);
    res.status(500).json({ success: false, error: "Failed to compute market signals" });
  }
});

hypeCycleRouter.get("/:tech", (req: Request, res: Response) => {
  const techQuery = String(req.params.tech);
  const yearParam = q("year", req);
  const year = yearParam ? parseInt(yearParam) : new Date().getFullYear();

  const tech = findTechnology(techQuery);
  if (!tech) {
    res.status(404).json({
      success: false,
      error: `Technology "${techQuery}" not found. Available: 1G, 10G, 25G, 40G, 100G, 400G, 800G, 1.6T, CPO, LPO, 400ZR`,
    });
    return;
  }

  const result = computeHypeCycle(tech, year);

  // Add regional data
  const regions = computeRegionalAdoption(tech.peakYear, year, tech.name);

  // Add revenue lifecycle
  const lifecycle = computeRevenueLifecycle(
    tech.speedGbps,
    tech.name,
    tech.introYear,
    tech.peakYear,
    year,
  );

  res.json({
    success: true,
    ...result,
    regionalAdoption: regions,
    revenueLifecycle: lifecycle,
  });
});
