import { NextResponse } from "next/server";
import { getPool } from "@/lib/db";

interface WeightRow {
  group_manufacturer: string;
  group_ingot: string;
  group_count: number;
  records: Array<{ row_index: number; G?: string }>;
}

interface TransformedGroup {
  group_name: string;
  group_count: number;
  rows_string: string;
}

const TABLE_CONFIG: { table: string; incomingKey: string }[] = [
  { table: "site_daily_by_manufacturer_weight", incomingKey: "site" },
  { table: "snapp_next_day_by_manufacturer_weight", incomingKey: "nextDay" },
  { table: "snapp_daily_by_manufacturer_weight", incomingKey: "snapp" },
  { table: "digi_daily_by_manufacturer_weight", incomingKey: "digikala" },
  { table: "express_daily_by_manufacturer_weight", incomingKey: "express" },
  { table: "tapsi_express_daily_by_manufacturer_weight", incomingKey: "tapsiExpress" },
  { table: "techno_by_manufacturer_weight", incomingKey: "techno" },
  { table: "digi_massnoat_daily_by_manufacturer_weight", incomingKey: "digikala_masnoat" },
];

const INCOMING_PARENT_MAP: Record<string, string> = {
  site: "site",
  digikala: "digi",
  digikala_masnoat: "digiMassnoat",
  snapp: "snapp",
  express: "express",
  nextDay: "nextDay",
  tapsiExpress: "tapsiExpress",
  techno: "techno",
};

function transformWeightData(rows: WeightRow[]): TransformedGroup[] {
  const grouped: Record<string, {
    group_name: string;
    group_count: number;
    rows: number[];
  }> = {};

  for (const item of rows) {
    const groupName = `${item.group_manufacturer}[${item.group_ingot}]`;
    if (!grouped[groupName]) {
      grouped[groupName] = {
        group_name: groupName,
        group_count: 0,
        rows: [],
      };
    }
    grouped[groupName].group_count += (item.records || []).length;
    for (const r of item.records || []) {
      grouped[groupName].rows.push(r.row_index);
    }
  }

  return Object.values(grouped).map((g) => {
    g.rows.sort((a, b) => a - b);
    return {
      group_name: g.group_name,
      group_count: g.group_count,
      rows_string: g.rows.join(","),
    };
  });
}

function buildOutput(allEntries: { incomingKey: string; group: TransformedGroup }[]) {
  const dailyG: Record<string, any[]> = {};
  for (const parent of Object.values(INCOMING_PARENT_MAP)) {
    dailyG[parent] = [];
  }

  for (const { incomingKey, group } of allEntries) {
    const parent = INCOMING_PARENT_MAP[incomingKey];
    if (!parent) continue;

    const rows = group.rows_string
      .split(",")
      .map(Number)
      .filter((n) => !isNaN(n));

    dailyG[parent].push({
      group_name: group.group_name,
      records: rows.map((r: number) => ({ G: "", row_index: r })),
    });
  }

  const parents = Object.values(INCOMING_PARENT_MAP);
  const output: {
    parent: string;
    group_name: string;
    objects_row_index: number[];
    count: number;
    type: string;
    key: string;
  }[] = [];

  for (const parent of parents) {
    const groups = dailyG[parent] || [];
    for (const g of groups) {
      if (g?.group_name && Array.isArray(g.records)) {
        output.push({
          parent,
          group_name: g.group_name,
          objects_row_index: g.records.map((r: any) => r.row_index),
          count: g.records.length,
          type: "",
          key: "",
        });
      }
    }
  }
  return [output];
}

// Cache state
let cachedData: any = null;
let cacheTimestamp = 0;
let refreshPromise: Promise<void> | null = null;
const CACHE_TTL_MS = 5 * 60 * 1000;

async function refreshCache() {
  try {
    const pool = getPool();
    const allEntries: { incomingKey: string; group: TransformedGroup }[] = [];

    for (const { table, incomingKey } of TABLE_CONFIG) {
      try {
        const [rows] = await pool.query(
          `SELECT group_manufacturer, group_ingot, group_count, records FROM \`${table}\``
        ) as unknown as [any[], any];
        const typedRows = rows as WeightRow[];
        if (typedRows.length > 0) {
          const transformed = transformWeightData(typedRows);
          for (const group of transformed) {
            allEntries.push({ incomingKey, group });
          }
        }
      } catch (err) {
        console.warn(`Error querying ${table}:`, err);
      }
    }

    cachedData = buildOutput(allEntries);
    cacheTimestamp = Date.now();
  } catch (err) {
    console.error("Error refreshing daily-g cache:", err);
  }
}

// Pre-warm cache on server start
const startupPromise = refreshCache();

export async function GET() {
  const now = Date.now();

  // Fresh cache: return immediately
  if (cachedData && now - cacheTimestamp < CACHE_TTL_MS) {
    return NextResponse.json(cachedData);
  }

  // Stale cache: return immediately, refresh in background
  if (cachedData) {
    if (!refreshPromise) {
      refreshPromise = refreshCache().finally(() => {
        refreshPromise = null;
      });
    }
    return NextResponse.json(cachedData);
  }

  // No cache yet: wait for startup query
  await startupPromise;
  if (cachedData) {
    return NextResponse.json(cachedData);
  }

  return NextResponse.json({ error: "Failed to load data" }, { status: 500 });
}
