import { HomePageClient } from "@/components/HomePageClient";
import { PARKS } from "@/lib/parks";
import { openDb, getDateRange } from "@/lib/db";
import { getTodayLocal, isWithinOperatingWindow, getOperatingStatus } from "@/lib/env";
import { fetchLiveRides } from "@/lib/scrapers/queuetimes";
import { QUEUE_TIMES_IDS } from "@/lib/queue-times-map";
import { readParkMeta, getCoasterSet } from "@/lib/park-meta";

interface PageProps {
  searchParams: Promise<{ week?: string }>;
}

function getWeekStart(param: string | undefined): string {
  if (param && /^\d{4}-\d{2}-\d{2}$/.test(param)) {
    const d = new Date(param + "T00:00:00");
    if (!isNaN(d.getTime())) {
      d.setDate(d.getDate() - d.getDay());
      return d.toISOString().slice(0, 10);
    }
  }
  const todayIso = getTodayLocal();
  const d = new Date(todayIso + "T00:00:00");
  d.setDate(d.getDate() - d.getDay());
  return d.toISOString().slice(0, 10);
}

function getWeekDates(sundayIso: string): string[] {
  return Array.from({ length: 7 }, (_, i) => {
    const d = new Date(sundayIso + "T00:00:00");
    d.setDate(d.getDate() + i);
    return d.toISOString().slice(0, 10);
  });
}

function getCurrentWeekStart(): string {
  const todayIso = getTodayLocal();
  const d = new Date(todayIso + "T00:00:00");
  d.setDate(d.getDate() - d.getDay());
  return d.toISOString().slice(0, 10);
}

export default async function HomePage({ searchParams }: PageProps) {
  const params = await searchParams;
  const weekStart = getWeekStart(params.week);
  const weekDates = getWeekDates(weekStart);
  const endDate = weekDates[6];
  const today = getTodayLocal();
  const isCurrentWeek = weekStart === getCurrentWeekStart();

  const db = openDb();
  const data = getDateRange(db, weekStart, endDate);
  db.close();

  const scrapedCount = Object.values(data).reduce(
    (sum, parkData) => sum + Object.keys(parkData).length,
    0
  );

  // Always fetch both ride and coaster counts — the client decides which to display.
  const parkMeta = readParkMeta();
  const hasCoasterData = PARKS.some((p) => (parkMeta[p.id]?.coasters.length ?? 0) > 0);

  let rideCounts: Record<string, number> = {};
  let coasterCounts: Record<string, number> = {};
  let closingParkIds: string[] = [];
  if (weekDates.includes(today)) {
    const openTodayParks = PARKS.filter((p) => {
      const dayData = data[p.id]?.[today];
      if (!dayData?.isOpen || !QUEUE_TIMES_IDS[p.id] || !dayData.hoursLabel) return false;
      return isWithinOperatingWindow(dayData.hoursLabel, p.timezone);
    });
    closingParkIds = openTodayParks
      .filter((p) => {
        const dayData = data[p.id]?.[today];
        return dayData?.hoursLabel
          ? getOperatingStatus(dayData.hoursLabel, p.timezone) === "closing"
          : false;
      })
      .map((p) => p.id);
    const results = await Promise.all(
      openTodayParks.map(async (p) => {
        const coasterSet = getCoasterSet(p.id, parkMeta);
        const result = await fetchLiveRides(QUEUE_TIMES_IDS[p.id], coasterSet, 300);
        const rideCount = result ? result.rides.filter((r) => r.isOpen).length : 0;
        const coasterCount = result ? result.rides.filter((r) => r.isOpen && r.isCoaster).length : 0;
        return { id: p.id, rideCount, coasterCount };
      })
    );
    rideCounts = Object.fromEntries(
      results.filter(({ rideCount }) => rideCount > 0).map(({ id, rideCount }) => [id, rideCount])
    );
    coasterCounts = Object.fromEntries(
      results.filter(({ coasterCount }) => coasterCount > 0).map(({ id, coasterCount }) => [id, coasterCount])
    );
  }

  return (
    <HomePageClient
      weekStart={weekStart}
      weekDates={weekDates}
      today={today}
      isCurrentWeek={isCurrentWeek}
      data={data}
      rideCounts={rideCounts}
      coasterCounts={coasterCounts}
      closingParkIds={closingParkIds}
      hasCoasterData={hasCoasterData}
      scrapedCount={scrapedCount}
    />
  );
}
