import { NextRequest, NextResponse } from "next/server";

/**
 * Server-side proxy for the customer panel's real per-service subject list.
 *
 * `calculator3.js` (`get_subject_list()`) POSTs to `api/get_subjects` and
 * injects the raw HTML `<select>` it gets back into the page. That endpoint
 * is the actual source of the order form's "Select Subject" options — the
 * Samples category list this app substituted before was a stand-in, not the
 * real list, and it carried no `addonprice`. `price_calculateNew` (see
 * `app/api/price/route.ts`) needs that addonprice: it's a per-subject
 * surcharge that can multiply the price by 20x (verified — addonprice 10000
 * moved a $5.66 quote to $122.66), so treating subjects as decorative would
 * make the price wrong, not just the label.
 *
 * The panel returns HTML, not JSON, so it's parsed here rather than passed
 * through — this app has no HTML-parsing dependency, so a small regex walk
 * is used instead of adding one for a single, fixed, panel-controlled shape.
 */

const PANEL_URL = process.env.NEXT_PUBLIC_CPANEL_URL || "https://customerpanel.globalassignmenthelp.com";

export interface SubjectOption {
  label: string;
  /** `sub_id` — the one field that's actually unique per row; see below. */
  value: string;
  addonPrice: number;
  group: string | null;
}

const OPTGROUP_RE = /<optgroup label="([^"]*)">/g;
// The panel's real markup wraps each <option>'s attributes across several
// lines (verified against a live response), so this can't assume they're on
// one line — `[\s\S]*?` between `sub_id` and `data-addonprice` covers that.
//
// `value="..."` is NOT unique — verified against a live 119-subject response,
// it only took 4 distinct values total (it's a broader group id the panel's
// own JS reads separately). `sub_id='...'` is the one that's actually unique
// per row, so that's what this app treats as each subject's id — using
// `value` would make most subjects visually indistinguishable in a native
// <select> (selecting "Healthcare" would silently resolve to whichever
// subject sharing its `value` happens to come first in the list).
const OPTION_RE =
  /<option\s+data-level="[^"]*"\s+sub_id='([^']*)'[\s\S]*?data-addonprice="([^"]*)"\s+value="([^"]*)"\s*>([^<]*)<\/option>/g;

function parseSubjectsHtml(html: string): SubjectOption[] {
  // Walk the string once, tracking the most recent <optgroup> label so each
  // <option> found after it is attributed to that group — mirrors how the
  // browser would read this markup, without a DOM.
  const markers: Array<{ index: number; group: string }> = [];
  for (const match of html.matchAll(OPTGROUP_RE)) {
    markers.push({ index: match.index ?? 0, group: match[1].trim() });
  }

  const options: SubjectOption[] = [];
  for (const match of html.matchAll(OPTION_RE)) {
    const index = match.index ?? 0;
    const subId = match[1].trim();
    const groupValue = match[3].trim();
    if (!subId || !groupValue) continue; // skip the "Select Subject" placeholder
    let group: string | null = null;
    for (const marker of markers) {
      if (marker.index <= index) group = marker.group;
      else break;
    }
    options.push({
      label: match[4].trim(),
      value: subId,
      addonPrice: Number(match[2]) || 0,
      group,
    });
  }
  return options;
}

export async function POST(request: NextRequest) {
  const { groupId, unitTag, serviceName } = await request.json();

  if (!groupId) {
    return NextResponse.json({ error: "groupId is required" }, { status: 400 });
  }

  const body = new URLSearchParams({
    g_id: String(groupId),
    unit_tag: unitTag || "",
    assignment_subject_nm: serviceName || "",
    urgency: " ",
    service_group_id: String(groupId),
    service_group_name: serviceName || "",
    type: "web",
  });

  try {
    const controller = new AbortController();
    const timeout = setTimeout(() => controller.abort(), 8000);

    const response = await fetch(`${PANEL_URL}/api/get_subjects`, {
      method: "POST",
      headers: { "Content-Type": "application/x-www-form-urlencoded" },
      body,
      signal: controller.signal,
      cache: "no-store",
    });
    clearTimeout(timeout);

    if (!response.ok) {
      return NextResponse.json({ error: "Panel returned an error" }, { status: 502 });
    }

    const html = await response.text();
    return NextResponse.json({ subjects: parseSubjectsHtml(html) });
  } catch {
    return NextResponse.json({ error: "Subject service unreachable" }, { status: 504 });
  }
}
