/**
 * Bulk Price Lookup
 *
 * Routes:
 *   POST /api/bulk-price   — Get current prices for multiple part numbers at once
 */
import { Router, Request, Response } from "express";
import { pool } from "../db/client";

export const bulkPriceRouter = Router();

const MAX_PART_NUMBERS = 100;

// ─── POST /api/bulk-price ─────────────────────────────────────────────────────
bulkPriceRouter.post("/", async (req: Request, res: Response) => {
  try {
    const { part_numbers, limit } = req.body as {
      part_numbers?: unknown;
      limit?: unknown;
    };

    if (!Array.isArray(part_numbers) || part_numbers.length === 0) {
      res.status(400).json({ success: false, error: "part_numbers must be a non-empty array" });
      return;
    }

    const safe = part_numbers
      .filter((p): p is string => typeof p === "string" && p.trim().length > 0)
      .slice(0, MAX_PART_NUMBERS)
      .map((p) => p.trim());

    if (safe.length === 0) {
      res.status(400).json({ success: false, error: "No valid part numbers provided" });
      return;
    }

    const perVendorLimit = typeof limit === "number" && limit > 0 ? Math.min(limit, 50) : 10;

    // Build $1,$2,... placeholders for the IN clause
    const placeholders = safe.map((_, i) => `$${i + 1}`).join(", ");

    const result = await pool.query<{
      part_number: string;
      transceiver_id: number;
      model_name: string;
      form_factor: string;
      speed_gbps: number;
      vendor_id: number;
      vendor_name: string;
      price: string;
      currency: string;
      observed_at: Date;
    }>(
      `WITH matched AS (
        SELECT id, part_number, COALESCE(standard_name, part_number, '') AS model_name, form_factor, speed_gbps
        FROM transceivers
        WHERE part_number ILIKE ANY (ARRAY[${placeholders}])
      ),
      recent_prices AS (
        SELECT DISTINCT ON (po.transceiver_id, po.source_vendor_id)
          po.transceiver_id,
          po.source_vendor_id,
          po.price,
          po.currency,
          po.time AS observed_at
        FROM price_observations po
        JOIN matched m ON m.id = po.transceiver_id
        WHERE po.time > NOW() - INTERVAL '30 days'
        ORDER BY po.transceiver_id, po.source_vendor_id, po.time DESC
      )
      SELECT
        m.part_number,
        m.id           AS transceiver_id,
        m.model_name,
        m.form_factor,
        m.speed_gbps,
        v.id           AS vendor_id,
        v.name         AS vendor_name,
        rp.price,
        rp.currency,
        rp.observed_at
      FROM matched m
      LEFT JOIN recent_prices rp ON rp.transceiver_id = m.id
      LEFT JOIN vendors v ON v.id = rp.source_vendor_id
      ORDER BY m.part_number, rp.price ASC NULLS LAST
      LIMIT $${safe.length + 1}`,
      [...safe, safe.length * perVendorLimit]
    );

    // Group rows by part_number
    type PriceEntry = {
      vendor_id: number;
      vendor_name: string;
      price_usd: number;  // normalised name for API output
      currency: string;
      observed_at: string;
    };
    type ResultEntry = {
      part_number: string;
      transceiver_id: number;
      model_name: string;
      form_factor: string;
      speed_gbps: number;
      prices: PriceEntry[];
      best_price_usd: number | null;
      price_count: number;
    };

    const map = new Map<string, ResultEntry>();

    for (const row of result.rows) {
      if (!map.has(row.part_number)) {
        map.set(row.part_number, {
          part_number: row.part_number,
          transceiver_id: row.transceiver_id,
          model_name: row.model_name,
          form_factor: row.form_factor,
          speed_gbps: row.speed_gbps,
          prices: [],
          best_price_usd: null,
          price_count: 0,
        });
      }
      const entry = map.get(row.part_number)!;
      if (row.vendor_id !== null && row.price !== null) {
        const priceNum = parseFloat(row.price);
        entry.prices.push({
          vendor_id: row.vendor_id,
          vendor_name: row.vendor_name,
          price_usd: priceNum,
          currency: row.currency,
          observed_at: row.observed_at.toISOString(),
        });
        if (entry.best_price_usd === null || priceNum < entry.best_price_usd) {
          entry.best_price_usd = priceNum;
        }
        entry.price_count += 1;
      }
    }

    const foundKeys = new Set(map.keys());
    const notFound = safe.filter(
      (pn) => !Array.from(foundKeys).some((k) => k.toLowerCase() === pn.toLowerCase())
    );

    res.json({
      success: true,
      results: Array.from(map.values()),
      total_found: map.size,
      not_found: notFound,
    });
  } catch (err) {
    console.error("POST /api/bulk-price error:", err);
    res.status(500).json({ success: false, error: String(err) });
  }
});
