import { Suspense } from "react";
import { ReportsPageClient } from "@/components/reports/ReportsPageClient";
import {
  aggregateEvents,
  aggregateReport,
  parseEventDateParam,
  parseEventGroupDimension,
  parseEventSplitDimension,
  parseEventType,
  parseGroupDimension,
  parseIsoDateParam,
  parseMeasure,
  parseMode,
  parseSplitDimension,
  sumValues,
  totalForRows,
} from "@/lib/reports";
import { loadEventHistory, loadOrgLookups, loadSnapshotEmployees } from "@/lib/reports-data";
import { createClient } from "@/lib/supabase/server";

type SearchParams = {
  mode?: string;
  measure?: string;
  group?: string;
  split?: string;
  division?: string;
  location?: string;
  status?: string;
  employment?: string;
  asOf?: string;
  eventType?: string;
  from?: string;
  to?: string;
};

export default async function ReportsPage({ searchParams }: { searchParams: Promise<SearchParams> }) {
  const params = await searchParams;
  const supabase = await createClient();
  const mode = parseMode(params.mode);

  // Both modes are parsed up front so the data load can start before
  // anything is awaited. They group by different dimension sets, so the
  // parsed values stay separate rather than being widened into one type.
  const asOf = parseIsoDateParam(params.asOf);
  const eventGroup = parseEventGroupDimension(params.group);
  const eventSplit = parseEventSplitDimension(params.split);
  const eventType = parseEventType(params.eventType);
  const from = parseEventDateParam(params.from);
  const to = parseEventDateParam(params.to);
  const measure = parseMeasure(params.measure);
  const group = parseGroupDimension(params.group);
  const split = parseSplitDimension(params.split);

  // The report data depends on neither the org lookups nor on who is signed
  // in, so all three go out together. Against a hosted database a round trip
  // costs about as much as the query itself, which made this page's three
  // sequential waves its dominant cost.
  const [{ lookups, divisions, locations }, { data: userRes }, events, employees] = await Promise.all([
    loadOrgLookups(supabase),
    supabase.auth.getUser(),
    mode === "events"
      ? loadEventHistory(supabase, {
          eventType: eventType ?? undefined,
          division: params.division,
          location: params.location,
          from,
          to,
        })
      : Promise.resolve([]),
    mode === "snapshot"
      ? loadSnapshotEmployees(supabase, {
          division: params.division,
          location: params.location,
          status: params.status,
          employment: params.employment,
          asOf,
        })
      : Promise.resolve([]),
  ]);

  const user = userRes.user;
  // Still a wave of its own: it needs the user id the call above resolves.
  const { data: savedReports } = user
    ? await supabase.from("saved_reports").select("id, name, config").eq("created_by", user.id).order("created_at", { ascending: false })
    : { data: [] };

  if (mode === "events") {
    const rows = aggregateEvents(events, eventGroup, eventSplit, lookups);

    return (
      <Suspense>
        <ReportsPageClient
          mode="events"
          eventGroup={eventGroup}
          eventSplit={eventSplit ?? ""}
          eventType={eventType ?? ""}
          eventFilters={{ division: params.division ?? "", location: params.location ?? "", from: from ?? "", to: to ?? "" }}
          rows={rows}
          total={sumValues(rows)}
          recordCount={events.length}
          divisions={divisions}
          locations={locations}
          savedReports={savedReports ?? []}
        />
      </Suspense>
    );
  }

  const rows = aggregateReport(employees, measure, group, split, lookups, asOf);

  return (
    <Suspense>
      <ReportsPageClient
        mode="snapshot"
        measure={measure}
        group={group}
        split={split ?? ""}
        asOf={asOf ?? ""}
        filters={{
          division: params.division ?? "",
          location: params.location ?? "",
          status: params.status ?? "",
          employment: params.employment ?? "",
        }}
        rows={rows}
        total={totalForRows(rows, measure)}
        recordCount={employees.length}
        divisions={divisions}
        locations={locations}
        savedReports={savedReports ?? []}
      />
    </Suspense>
  );
}
