/**
 * Internal Demand API — Flexoptix Sales Velocity
 * ─────────────────────────────────────────────────────────────────────────────
 * ⚠️  SECURITY: This router ONLY serves aggregated, anonymized demand data.
 *     Raw SKU-level records (individual demand figures) are NEVER returned.
 *     The underlying table is protected by:
 *       1. PostgreSQL Row Level Security (RLS) — is_internal = TRUE guard
 *       2. This router never returns individual rows from flexoptix_internal_demand
 *       3. JWT auth middleware (requireAuth) in index.ts — all /api/* routes
 *
 *     Note: IP-restriction removed — Cloudflare tunnel rewrites X-Forwarded-For
 *     to the real user IP, so `trust proxy: 1` would block legitimate dashboard
 *     users. JWT is the real security boundary; RLS + aggregation handle the rest.
 *
 * Routes:
 *   GET /api/internal/demand/by-speed        — Aggregated demand by technology
 *   GET /api/internal/demand/velocity        — Velocity class breakdown (counts only)
 *   GET /api/internal/demand/hype-weights    — Demand-calibrated hype cycle weights
 *   GET /api/internal/demand/forecast-input  — Forecast calibration for Norton-Bass
 *   GET /api/internal/demand/stock-analysis  — Demand vs live webshop stock (combined)
 */

import { Router, Request, Response } from "express";
import { pool } from "../db/client";

export const internalDemandRouter = Router();

// ─── GET /api/internal/demand/by-speed ──────────────────────────────────────
/**
 * Aggregated demand totals by technology (speed_gbps × form_factor).
 * Safe to expose — no individual SKUs, only category sums.
 */
internalDemandRouter.get("/by-speed", async (_req: Request, res: Response) => {
  try {
    const { rows } = await pool.query(`
      SELECT
        t.speed_gbps,
        t.form_factor,
        COUNT(DISTINCT d.sku)                                             AS sku_count,
        ROUND(SUM(d.demand_12m))                                         AS total_demand_12m,
        ROUND(SUM(d.demand_3m))                                          AS total_demand_3m,
        ROUND(AVG(d.demand_12m), 1)                                      AS avg_demand_12m,
        ROUND(AVG(d.demand_3m), 1)                                       AS avg_demand_3m,
        ROUND(AVG(COALESCE(d.demand_trend_pct, 0)), 1)                   AS avg_trend_pct,
        COUNT(*) FILTER (WHERE d.velocity_class = 'fast_mover')          AS fast_movers,
        COUNT(*) FILTER (WHERE d.velocity_class = 'regular')              AS regular,
        COUNT(*) FILTER (WHERE d.velocity_class = 'slow_mover')           AS slow_movers,
        -- Momentum: 3m vs 12m ratio (>1 = accelerating)
        ROUND(
          CASE WHEN SUM(d.demand_12m) > 0
               THEN SUM(d.demand_3m) / SUM(d.demand_12m)
               ELSE 1 END,
          3
        )                                                                  AS momentum_ratio
      FROM flexoptix_internal_demand d
      JOIN transceivers t ON t.id = d.transceiver_id
      WHERE d.demand_12m > 0
      GROUP BY t.speed_gbps, t.form_factor
      ORDER BY total_demand_12m DESC
    `);

    res.json({ success: true, data: rows });
  } catch (err) {
    console.error("GET /api/internal/demand/by-speed error:", err);
    res.status(500).json({ success: false, error: "Internal server error" });
  }
});

// ─── GET /api/internal/demand/velocity ──────────────────────────────────────
/**
 * Velocity class distribution across all 8,585 SKUs.
 */
internalDemandRouter.get("/velocity", async (_req: Request, res: Response) => {
  try {
    const { rows } = await pool.query(`
      SELECT
        velocity_class,
        COUNT(*)                    AS sku_count,
        ROUND(SUM(demand_12m))      AS total_demand_12m,
        ROUND(AVG(demand_12m), 1)   AS avg_demand_12m,
        MAX(demand_12m)             AS peak_demand_12m
      FROM flexoptix_internal_demand
      GROUP BY velocity_class
      ORDER BY total_demand_12m DESC
    `);

    const total = rows.reduce((s, r) => s + parseInt(r.sku_count, 10), 0);

    res.json({
      success: true,
      data: {
        total_skus: total,
        classes: rows.map(r => ({
          ...r,
          share_pct: Math.round((parseInt(r.sku_count, 10) / total) * 1000) / 10,
        })),
      },
    });
  } catch (err) {
    console.error("GET /api/internal/demand/velocity error:", err);
    res.status(500).json({ success: false, error: "Internal server error" });
  }
});

// ─── GET /api/internal/demand/hype-weights ──────────────────────────────────
/**
 * Returns demand-calibrated weights per technology for hype cycle recalibration.
 * Maps real Flexoptix sales velocity to Norton-Bass market potential (m) adjustments.
 *
 * Logic:
 *   - Normalize total_demand_12m across all technologies → relative weight 0–1
 *   - Momentum ratio > 1 = accelerating (positive hype signal)
 *   - momentum ratio < 1 = decelerating (trough/plateau signal)
 */
internalDemandRouter.get("/hype-weights", async (_req: Request, res: Response) => {
  try {
    const { rows } = await pool.query(`
      WITH base AS (
        SELECT
          t.speed_gbps,
          t.form_factor,
          SUM(d.demand_12m)   AS demand_12m,
          SUM(d.demand_3m)    AS demand_3m,
          COUNT(d.sku)        AS sku_count
        FROM flexoptix_internal_demand d
        JOIN transceivers t ON t.id = d.transceiver_id
        WHERE d.demand_12m > 0
        GROUP BY t.speed_gbps, t.form_factor
      ),
      totals AS (
        SELECT SUM(demand_12m) AS grand_total FROM base
      )
      SELECT
        b.speed_gbps,
        b.form_factor,
        b.sku_count,
        ROUND(b.demand_12m)                                              AS demand_12m,
        ROUND(b.demand_3m)                                               AS demand_3m,
        -- Normalized weight (0–1), sum = 1 across all techs
        ROUND(b.demand_12m / t.grand_total, 4)                          AS demand_weight,
        -- Momentum ratio: 3m vs 12m (>1 = growing, <1 = declining)
        ROUND(
          CASE WHEN b.demand_12m > 0
               THEN b.demand_3m / b.demand_12m
               ELSE 1 END, 3
        )                                                                AS momentum_ratio,
        -- Suggested hype signal based on momentum
        CASE
          WHEN b.demand_3m / NULLIF(b.demand_12m, 0) > 1.15 THEN 'climbing'
          WHEN b.demand_3m / NULLIF(b.demand_12m, 0) > 0.90 THEN 'stable'
          WHEN b.demand_3m / NULLIF(b.demand_12m, 0) > 0.70 THEN 'cooling'
          ELSE 'declining'
        END                                                              AS demand_signal
      FROM base b, totals t
      ORDER BY demand_weight DESC
    `);

    res.json({ success: true, data: rows });
  } catch (err) {
    console.error("GET /api/internal/demand/hype-weights error:", err);
    res.status(500).json({ success: false, error: "Internal server error" });
  }
});

// ─── GET /api/internal/demand/forecast-input ────────────────────────────────
/**
 * Structured forecast calibration input for the Norton-Bass engine.
 * Provides real-demand scaling factors for the volume forecast.
 *
 * Use in forecast.ts to replace the `totalMarketPorts * marketShare` estimate
 * with real observed Flexoptix throughput per technology.
 */
internalDemandRouter.get("/forecast-input", async (_req: Request, res: Response) => {
  try {
    const { rows } = await pool.query(`
      SELECT
        t.speed_gbps,
        t.form_factor,
        ROUND(SUM(d.demand_12m))                                         AS units_per_month_12m,
        ROUND(SUM(d.demand_3m))                                          AS units_per_month_3m,
        ROUND(SUM(d.demand_12m) * 12)                                    AS units_annual_run_rate,
        ROUND(
          CASE WHEN SUM(d.demand_12m) > 0
               THEN SUM(d.demand_3m) / SUM(d.demand_12m)
               ELSE 1 END, 3
        )                                                                 AS growth_factor,
        -- Projected units for 3m forecast using 3m run-rate
        ROUND(SUM(d.demand_3m) * 3)                                      AS projected_units_3m,
        -- Projected units for 12m forecast using 12m run-rate with momentum
        ROUND(
          SUM(d.demand_12m) * 12 *
          GREATEST(0.5, LEAST(2.0,
            CASE WHEN SUM(d.demand_12m) > 0
                 THEN SUM(d.demand_3m) / SUM(d.demand_12m)
                 ELSE 1 END
          ))
        )                                                                 AS projected_units_12m
      FROM flexoptix_internal_demand d
      JOIN transceivers t ON t.id = d.transceiver_id
      WHERE d.demand_12m > 0 OR d.demand_3m > 0
      GROUP BY t.speed_gbps, t.form_factor
      ORDER BY units_per_month_12m DESC
    `);

    res.json({
      success: true,
      data: rows,
      meta: {
        note: "Aggregated Flexoptix throughput — safe for dashboard use. No raw SKU data exposed.",
        source: "flexoptix_internal_demand",
        last_updated: new Date().toISOString(),
      },
    });
  } catch (err) {
    console.error("GET /api/internal/demand/forecast-input error:", err);
    res.status(500).json({ success: false, error: "Internal server error" });
  }
});

// ─── GET /api/internal/demand/stock-analysis ────────────────────────────────
/**
 * Combined analysis: internal Flexoptix demand vs live webshop stock observations.
 *
 * Joins flexoptix_internal_demand (real sales velocity) with the latest
 * stock_observations scraped from flexoptix.net and other sources.
 *
 * Returns per-transceiver:
 *   - demand_12m / demand_3m: real monthly demand from internal XLSX
 *   - webshop_de_qty: current DE-Lager from live scrape
 *   - webshop_global_qty: current Global-Lager
 *   - coverage_days_de: how many days current DE stock covers demand
 *   - reorder_urgency: 'critical' | 'low' | 'ok' | 'overstocked'
 *   - momentum_ratio: 3m vs 12m demand trend
 *
 * This is the foundation for continuous procurement analysis.
 * Safe to expose — no individual SKU demand figures, data aggregated per transceiver.
 */
internalDemandRouter.get("/stock-analysis", async (_req: Request, res: Response) => {
  try {
    const { rows } = await pool.query(`
      WITH latest_stock AS (
        -- Most recent stock observation per transceiver from Flexoptix vendor
        SELECT DISTINCT ON (so.transceiver_id)
          so.transceiver_id,
          so.warehouse_de_qty,
          so.warehouse_global_qty,
          so.backorder_qty,
          so.in_stock,
          so.price_net,
          so.price_currency,
          so.units_sold          AS scraper_units_sold,
          so.time                AS last_scraped
        FROM stock_observations so
        JOIN vendors v ON v.id = so.source_vendor_id
        WHERE v.slug ILIKE '%flexoptix%'
           OR v.website ILIKE '%flexoptix%'
        ORDER BY so.transceiver_id, so.time DESC
      ),
      all_vendors_stock AS (
        -- Also grab best available stock from ANY vendor if no Flexoptix data
        SELECT DISTINCT ON (so.transceiver_id)
          so.transceiver_id,
          so.warehouse_de_qty     AS any_de_qty,
          so.warehouse_global_qty AS any_global_qty,
          so.in_stock             AS any_in_stock,
          so.price_net            AS any_price,
          so.time                 AS any_scraped
        FROM stock_observations so
        ORDER BY so.transceiver_id, so.time DESC
      )
      SELECT
        t.part_number,
        t.form_factor,
        t.speed_gbps,
        t.fiber_type,

        -- Internal demand (real Flexoptix sales velocity)
        d.demand_12m,
        d.demand_3m,
        d.velocity_class,
        ROUND(d.demand_trend_pct, 1)          AS demand_trend_pct,

        -- Live webshop stock (Flexoptix-specific if available, else any vendor)
        COALESCE(ls.warehouse_de_qty,     avs.any_de_qty,     0) AS webshop_de_qty,
        COALESCE(ls.warehouse_global_qty, avs.any_global_qty, 0) AS webshop_global_qty,
        COALESCE(ls.in_stock,             avs.any_in_stock, false) AS webshop_in_stock,
        COALESCE(ls.price_net,            avs.any_price)          AS webshop_price,
        COALESCE(ls.last_scraped,         avs.any_scraped)        AS last_scraped,
        ls.scraper_units_sold,

        -- Coverage analysis: how many days does current DE stock cover demand?
        CASE
          WHEN d.demand_12m > 0 AND COALESCE(ls.warehouse_de_qty, avs.any_de_qty, 0) > 0
          THEN ROUND(
            COALESCE(ls.warehouse_de_qty, avs.any_de_qty, 0)::NUMERIC
            / (d.demand_12m / 30.0)
          )
          ELSE NULL
        END AS coverage_days_de,

        -- Reorder urgency signal
        CASE
          WHEN d.demand_12m = 0 THEN 'no_demand'
          WHEN COALESCE(ls.warehouse_de_qty, avs.any_de_qty, 0) = 0
               AND d.demand_12m >= 10 THEN 'critical'
          WHEN COALESCE(ls.warehouse_de_qty, avs.any_de_qty, 0)::NUMERIC
               / NULLIF(d.demand_12m / 30.0, 0) < 14
               AND d.demand_12m >= 10 THEN 'low'
          WHEN COALESCE(ls.warehouse_de_qty, avs.any_de_qty, 0)::NUMERIC
               / NULLIF(d.demand_12m / 30.0, 0) > 90
               AND d.demand_12m > 0 THEN 'overstocked'
          ELSE 'ok'
        END AS reorder_urgency,

        -- Momentum
        ROUND(
          CASE WHEN d.demand_12m > 0
               THEN d.demand_3m / d.demand_12m ELSE 1 END, 3
        ) AS momentum_ratio

      FROM flexoptix_internal_demand d
      JOIN transceivers t ON t.id = d.transceiver_id
      LEFT JOIN latest_stock ls ON ls.transceiver_id = d.transceiver_id
      LEFT JOIN all_vendors_stock avs ON avs.transceiver_id = d.transceiver_id
      WHERE d.demand_12m > 0 OR d.demand_3m > 0
      ORDER BY d.demand_12m DESC
    `);

    // Summary stats
    const critical = rows.filter(r => r.reorder_urgency === "critical").length;
    const low      = rows.filter(r => r.reorder_urgency === "low").length;
    const ok       = rows.filter(r => r.reorder_urgency === "ok").length;
    const overstock = rows.filter(r => r.reorder_urgency === "overstocked").length;
    const withStock = rows.filter(r => parseInt(r.webshop_de_qty ?? "0", 10) > 0).length;

    res.json({
      success: true,
      data: rows,
      summary: {
        total_active_skus: rows.length,
        with_de_stock: withStock,
        reorder_critical: critical,
        reorder_low: low,
        reorder_ok: ok,
        overstocked: overstock,
      },
      meta: {
        note: "Demand (internal) × Live stock (scraped). Aggregated per transceiver, no raw demand SKUs.",
        last_updated: new Date().toISOString(),
      },
    });
  } catch (err) {
    console.error("GET /api/internal/demand/stock-analysis error:", err);
    res.status(500).json({ success: false, error: "Internal server error" });
  }
});
