/**
 * Stock Observations API
 *
 * Exposes warehouse stock data scraped from fs.com (DE-Lager, Global-Lager,
 * Nachlieferung, units_sold, compatible_brands) and other vendors.
 *
 * Routes:
 *   GET /api/stock                         — Latest obs per transceiver × vendor (paginated)
 *   GET /api/stock/summary                 — Aggregate warehouse stats (totals, top movers)
 *   GET /api/stock/:transceiverIdOrSku     — Full obs history for one transceiver
 */
import { Router, Request, Response } from "express";
import { pool } from "../db/client";

export const stockRouter = Router();

// ─── helpers ─────────────────────────────────────────────────────────────────

function intParam(req: Request, name: string, fallback: number): number {
  const v = req.query[name];
  const parsed = v ? parseInt(String(v), 10) : NaN;
  return Number.isFinite(parsed) ? parsed : fallback;
}

// ─── GET /api/stock ──────────────────────────────────────────────────────────
/**
 * Returns the most recent stock observation per (transceiver, vendor) pair.
 * Query params:
 *   vendor_id   — filter by source vendor UUID
 *   in_stock    — "true" | "false"
 *   min_de      — minimum DE-Lager quantity
 *   min_global  — minimum Global-Lager quantity
 *   part_number — partial match on part_number
 *   limit       — default 50, max 200
 *   offset      — default 0
 */
stockRouter.get("/", async (req: Request, res: Response) => {
  try {
    const limit = Math.min(intParam(req, "limit", 50), 200);
    const offset = intParam(req, "offset", 0);
    const vendorId = req.query.vendor_id ? String(req.query.vendor_id) : null;
    const inStock = req.query.in_stock === "true" ? true : req.query.in_stock === "false" ? false : null;
    const minDe = req.query.min_de ? parseInt(String(req.query.min_de), 10) : null;
    const minGlobal = req.query.min_global ? parseInt(String(req.query.min_global), 10) : null;
    const partNumber = req.query.part_number ? String(req.query.part_number) : null;

    const conditions: string[] = [];
    const params: unknown[] = [];
    let p = 1;

    if (vendorId) { conditions.push(`so.source_vendor_id = $${p++}`); params.push(vendorId); }
    if (inStock !== null) { conditions.push(`so.in_stock = $${p++}`); params.push(inStock); }
    if (minDe !== null) { conditions.push(`so.warehouse_de_qty >= $${p++}`); params.push(minDe); }
    if (minGlobal !== null) { conditions.push(`so.warehouse_global_qty >= $${p++}`); params.push(minGlobal); }
    if (partNumber) { conditions.push(`t.part_number ILIKE $${p++}`); params.push(`%${partNumber}%`); }

    const whereClause = conditions.length ? `AND ${conditions.join(" AND ")}` : "";

    const sql = `
      SELECT
        so.time,
        t.id                       AS transceiver_id,
        t.part_number,
        t.form_factor,
        t.speed,
        v.name                     AS vendor_name,
        v.website                  AS vendor_website,
        so.in_stock,
        so.quantity_available,
        so.warehouse_de_qty,
        so.warehouse_de_delivery_date,
        so.warehouse_global_qty,
        so.warehouse_global_delivery_date,
        so.backorder_qty,
        so.backorder_estimated_date,
        so.units_sold,
        so.compatible_brands,
        so.price_net,
        so.product_url,
        so.stock_confidence,
        so.price_currency,
        so.price_includes_tax,
        so.stock_vendor_ts
      FROM (
        SELECT DISTINCT ON (transceiver_id, source_vendor_id) *
        FROM stock_observations
        ORDER BY transceiver_id, source_vendor_id, time DESC
      ) so
      JOIN transceivers t ON t.id = so.transceiver_id
      JOIN vendors v ON v.id = so.source_vendor_id
      WHERE 1=1 ${whereClause}
      ORDER BY so.time DESC
      LIMIT $${p++} OFFSET $${p++}
    `;
    params.push(limit, offset);

    const countSql = `
      SELECT COUNT(*) FROM (
        SELECT DISTINCT ON (transceiver_id, source_vendor_id) *
        FROM stock_observations
        ORDER BY transceiver_id, source_vendor_id, time DESC
      ) so
      JOIN transceivers t ON t.id = so.transceiver_id
      JOIN vendors v ON v.id = so.source_vendor_id
      WHERE 1=1 ${whereClause}
    `;

    const [rows, countRow] = await Promise.all([
      pool.query(sql, params),
      pool.query(countSql, params.slice(0, params.length - 2)),
    ]);

    res.json({
      success: true,
      data: rows.rows,
      meta: {
        total: parseInt(countRow.rows[0].count, 10),
        limit,
        offset,
      },
    });
  } catch (err) {
    console.error("GET /api/stock error:", err);
    res.status(500).json({ success: false, error: "Internal server error" });
  }
});

// ─── GET /api/stock/summary ──────────────────────────────────────────────────
/**
 * Aggregate stats across all latest stock observations.
 * Returns totals per warehouse tier, top sellers, and per-vendor breakdown.
 */
stockRouter.get("/summary", async (req: Request, res: Response) => {
  try {
    const [totals, topSellers, vendorBreakdown, recentlyUpdated, priceComparison] = await Promise.all([
      // Overall totals from latest observations
      pool.query(`
        WITH latest AS (
          SELECT DISTINCT ON (transceiver_id, source_vendor_id) *
          FROM stock_observations
          ORDER BY transceiver_id, source_vendor_id, time DESC
        )
        SELECT
          COUNT(*)                                                AS total_observations,
          COUNT(*) FILTER (WHERE in_stock = true)                AS in_stock_count,
          SUM(COALESCE(warehouse_de_qty, 0))                     AS total_de_qty,
          SUM(COALESCE(warehouse_global_qty, 0))                 AS total_global_qty,
          SUM(COALESCE(backorder_qty, 0))                        AS total_backorder_qty,
          COUNT(*) FILTER (WHERE warehouse_de_qty > 0)           AS products_with_de_stock,
          COUNT(*) FILTER (WHERE warehouse_global_qty > 0)       AS products_with_global_stock,
          COUNT(*) FILTER (WHERE backorder_qty > 0)              AS products_with_backorder,
          COUNT(DISTINCT transceiver_id)                         AS unique_transceivers,
          COUNT(DISTINCT source_vendor_id)                       AS unique_vendors,
          -- Data quality breakdown by confidence level
          COUNT(*) FILTER (WHERE stock_confidence = 1)          AS conf_boolean_count,
          COUNT(*) FILTER (WHERE stock_confidence = 2)          AS conf_aggregated_count,
          COUNT(*) FILTER (WHERE stock_confidence = 3)          AS conf_per_warehouse_count,
          -- Multi-vendor coverage (SKUs tracked by 2+ vendors)
          COUNT(DISTINCT transceiver_id) FILTER (WHERE transceiver_id IN (
            SELECT transceiver_id FROM latest GROUP BY transceiver_id HAVING COUNT(DISTINCT source_vendor_id) >= 2
          ))                                                     AS multi_vendor_skus
        FROM latest
      `),

      // Top sellers by units_sold
      pool.query(`
        WITH latest AS (
          SELECT DISTINCT ON (transceiver_id, source_vendor_id) *
          FROM stock_observations
          WHERE units_sold IS NOT NULL
          ORDER BY transceiver_id, source_vendor_id, time DESC
        )
        SELECT
          t.part_number,
          t.form_factor,
          t.speed,
          v.name AS vendor_name,
          so.units_sold,
          so.warehouse_de_qty,
          so.warehouse_global_qty,
          so.price_net,
          so.product_url
        FROM latest so
        JOIN transceivers t ON t.id = so.transceiver_id
        JOIN vendors v ON v.id = so.source_vendor_id
        ORDER BY so.units_sold DESC
        LIMIT 20
      `),

      // Per-vendor stock breakdown (incl. confidence + currency breakdown)
      pool.query(`
        WITH latest AS (
          SELECT DISTINCT ON (transceiver_id, source_vendor_id) *
          FROM stock_observations
          ORDER BY transceiver_id, source_vendor_id, time DESC
        )
        SELECT
          v.name                                                          AS vendor_name,
          v.website                                                       AS vendor_website,
          COUNT(*)                                                        AS product_count,
          COUNT(*) FILTER (WHERE so.in_stock = true)                     AS in_stock_count,
          SUM(COALESCE(so.warehouse_de_qty, 0))                          AS total_de_qty,
          SUM(COALESCE(so.warehouse_global_qty, 0))                      AS total_global_qty,
          SUM(COALESCE(so.backorder_qty, 0))                             AS total_backorder,
          MAX(so.time)                                                    AS last_scraped,
          ROUND(AVG(so.stock_confidence)::NUMERIC, 1)                    AS avg_confidence,
          ARRAY_AGG(DISTINCT so.price_currency)
            FILTER (WHERE so.price_currency IS NOT NULL)                 AS currencies,
          -- Per-confidence breakdown
          COUNT(*) FILTER (WHERE so.stock_confidence = 3)               AS conf_per_warehouse,
          COUNT(*) FILTER (WHERE so.stock_confidence = 2)               AS conf_aggregated,
          COUNT(*) FILTER (WHERE so.stock_confidence = 1
            OR so.stock_confidence IS NULL)                              AS conf_boolean
        FROM latest so
        JOIN vendors v ON v.id = so.source_vendor_id
        GROUP BY v.id, v.name, v.website
        ORDER BY product_count DESC
      `),

      // Recently restocked (stock appeared in last 24h)
      pool.query(`
        SELECT
          t.part_number,
          t.form_factor,
          t.speed,
          v.name AS vendor_name,
          so.warehouse_de_qty,
          so.warehouse_global_qty,
          so.time AS observed_at
        FROM stock_observations so
        JOIN transceivers t ON t.id = so.transceiver_id
        JOIN vendors v ON v.id = so.source_vendor_id
        WHERE so.time >= NOW() - INTERVAL '24 hours'
          AND so.in_stock = true
          AND (so.warehouse_de_qty > 0 OR so.warehouse_global_qty > 0)
        ORDER BY so.time DESC
        LIMIT 10
      `),

      // Price comparison: SKUs tracked by multiple vendors (multi-vendor overlap)
      pool.query(`
        WITH latest AS (
          SELECT DISTINCT ON (transceiver_id, source_vendor_id) *
          FROM stock_observations
          WHERE price_net IS NOT NULL
          ORDER BY transceiver_id, source_vendor_id, time DESC
        )
        SELECT
          t.part_number,
          t.form_factor,
          t.speed,
          COUNT(DISTINCT so.source_vendor_id)        AS vendor_count,
          MIN(so.price_net)                          AS price_min,
          MAX(so.price_net)                          AS price_max,
          ROUND(AVG(so.price_net)::NUMERIC, 2)       AS price_avg,
          ARRAY_AGG(v.name ORDER BY so.price_net)    AS vendor_names,
          ARRAY_AGG(so.price_net ORDER BY so.price_net) AS prices,
          ARRAY_AGG(so.price_currency ORDER BY so.price_net) AS currencies,
          MAX(so.stock_confidence)                   AS best_confidence
        FROM latest so
        JOIN transceivers t ON t.id = so.transceiver_id
        JOIN vendors v ON v.id = so.source_vendor_id
        GROUP BY t.id, t.part_number, t.form_factor, t.speed
        HAVING COUNT(DISTINCT so.source_vendor_id) >= 2
        ORDER BY vendor_count DESC, price_min ASC
        LIMIT 50
      `),
    ]);

    res.json({
      success: true,
      data: {
        totals: totals.rows[0],
        top_sellers: topSellers.rows,
        vendor_breakdown: vendorBreakdown.rows,
        recently_updated: recentlyUpdated.rows,
        price_comparison: priceComparison.rows,
      },
    });
  } catch (err) {
    console.error("GET /api/stock/summary error:", err);
    res.status(500).json({ success: false, error: "Internal server error" });
  }
});

// ─── GET /api/stock/:id ──────────────────────────────────────────────────────
/**
 * Full observation history for one transceiver.
 * :id can be a UUID or a part_number (case-insensitive).
 * Query params:
 *   vendor_id — filter by vendor UUID
 *   days      — look-back window in days (default 30)
 *   limit     — max observations returned (default 100)
 */
stockRouter.get("/:id", async (req: Request, res: Response) => {
  try {
    const id = String(req.params.id);
    const days = intParam(req, "days", 30);
    const limit = Math.min(intParam(req, "limit", 100), 500);
    const vendorId = req.query.vendor_id ? String(req.query.vendor_id) : null;

    // Resolve UUID vs part_number
    let transceiverUuid: string | null = null;
    const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
    if (uuidRegex.test(id)) {
      transceiverUuid = id;
    } else {
      const r = await pool.query(
        `SELECT id FROM transceivers WHERE part_number ILIKE $1 LIMIT 1`,
        [id]
      );
      if (r.rows.length > 0) transceiverUuid = r.rows[0].id;
    }

    if (!transceiverUuid) {
      res.status(404).json({ success: false, error: "Transceiver not found" });
      return;
    }

    const params: unknown[] = [transceiverUuid, days, limit];
    let vendorFilter = "";
    if (vendorId) {
      params.push(vendorId);
      vendorFilter = `AND so.source_vendor_id = $${params.length}`;
    }

    const [transceiver, observations] = await Promise.all([
      pool.query(
        `SELECT t.*, v.name AS brand_name
         FROM transceivers t LEFT JOIN vendors v ON v.id = t.brand_vendor_id
         WHERE t.id = $1`,
        [transceiverUuid]
      ),
      pool.query(
        `SELECT
           so.time,
           v.name                         AS vendor_name,
           v.website                      AS vendor_website,
           so.in_stock,
           so.quantity_available,
           so.warehouse_de_qty,
           so.warehouse_de_delivery_date,
           so.warehouse_global_qty,
           so.warehouse_global_delivery_date,
           so.backorder_qty,
           so.backorder_estimated_date,
           so.units_sold,
           so.compatible_brands,
           so.price_net,
           so.product_url
         FROM stock_observations so
         JOIN vendors v ON v.id = so.source_vendor_id
         WHERE so.transceiver_id = $1
           AND so.time >= NOW() - ($2 || ' days')::INTERVAL
           ${vendorFilter}
         ORDER BY so.time DESC
         LIMIT $3`,
        params
      ),
    ]);

    if (!transceiver.rows[0]) {
      res.status(404).json({ success: false, error: "Transceiver not found" });
      return;
    }

    res.json({
      success: true,
      data: {
        transceiver: transceiver.rows[0],
        observations: observations.rows,
        meta: {
          count: observations.rows.length,
          days_requested: days,
        },
      },
    });
  } catch (err) {
    console.error("GET /api/stock/:id error:", err);
    res.status(500).json({ success: false, error: "Internal server error" });
  }
});
