import { Fragment } from "react";
import Link from "next/link";
import type { Park } from "@/lib/scrapers/types";
import type { DayData } from "@/lib/db";
import type { Region } from "@/lib/parks";
import { getTodayLocal, getTimezoneAbbr } from "@/lib/env";

interface WeekCalendarProps {
  parks: Park[];
  weekDates: string[]; // 7 dates, YYYY-MM-DD, Sun–Sat
  data: Record<string, Record<string, DayData>>; // parkId → date → DayData
  grouped?: Map<Region, Park[]>; // pre-grouped parks (if provided, renders region headers)
  rideCounts?: Record<string, number>; // parkId → open ride/coaster count for today
  coastersOnly?: boolean;
  closingParkIds?: string[]; // parks in the post-close wind-down buffer
}

const DOW = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
const MONTHS = [
  "Jan","Feb","Mar","Apr","May","Jun",
  "Jul","Aug","Sep","Oct","Nov","Dec",
];

function parseDate(iso: string) {
  const d = new Date(iso + "T00:00:00");
  return {
    month: d.getMonth(),
    day: d.getDate(),
    dow: d.getDay(),
    isWeekend: d.getDay() === 0 || d.getDay() === 6,
  };
}

function DayCell({
  dayData,
  isWeekend,
  tzAbbr,
}: {
  dayData: DayData | undefined;
  isWeekend: boolean;
  tzAbbr: string;
}) {
  const base: React.CSSProperties = {
    padding: 0,
    textAlign: "center",
    verticalAlign: "middle",
    borderBottom: "1px solid var(--color-border)",
    borderLeft: "1px solid var(--color-border)",
    height: 56,
    background: isWeekend ? "var(--color-weekend-header)" : "transparent",
    transition: "background 120ms ease",
  };

  if (!dayData) {
    return (
      <td style={base}>
        <span style={{ color: "var(--color-text-dim)", fontSize: "0.8rem" }}>—</span>
      </td>
    );
  }

  if (!dayData.isOpen || !dayData.hoursLabel) {
    return (
      <td style={base}>
        <span style={{ color: "var(--color-text-dim)", fontSize: "1rem", lineHeight: 1 }}>·</span>
      </td>
    );
  }

  if (dayData.specialType === "passholder_preview") {
    return (
      <td style={{ ...base, padding: 4 }}>
        <div style={{
          background: "var(--color-ph-bg)",
          border: "1px solid var(--color-ph-border)",
          borderRadius: 6,
          padding: "4px 4px",
          textAlign: "center",
          height: "100%",
          display: "flex",
          flexDirection: "column",
          alignItems: "center",
          justifyContent: "center",
          gap: 2,
          transition: "filter 150ms ease",
        }}>
          <span style={{
            color: "var(--color-ph-label)",
            fontSize: "0.58rem",
            fontWeight: 600,
            letterSpacing: "0.05em",
            textTransform: "uppercase",
            whiteSpace: "nowrap",
          }}>
            Passholder
          </span>
          <span style={{
            color: "var(--color-ph-hours)",
            fontSize: "0.78rem",
            fontWeight: 600,
            letterSpacing: "-0.01em",
            whiteSpace: "nowrap",
          }}>
            {dayData.hoursLabel}
          </span>
          <span style={{
            color: "var(--color-ph-label)",
            fontSize: "0.6rem",
            fontWeight: 500,
            letterSpacing: "0.04em",
          }}>
            {tzAbbr}
          </span>
        </div>
      </td>
    );
  }

  return (
    <td style={{ ...base, padding: 4 }}>
      <div style={{
        background: "var(--color-open-bg)",
        border: "1px solid var(--color-open-border)",
        borderRadius: 6,
        padding: "4px",
        textAlign: "center",
        height: "100%",
        display: "flex",
        flexDirection: "column",
        alignItems: "center",
        justifyContent: "center",
        gap: 2,
        transition: "filter 150ms ease",
      }}>
        <span style={{
          color: "var(--color-open-hours)",
          fontSize: "0.78rem",
          fontWeight: 600,
          letterSpacing: "-0.01em",
          whiteSpace: "nowrap",
        }}>
          {dayData.hoursLabel}
        </span>
        <span style={{
          color: "var(--color-open-hours)",
          fontSize: "0.6rem",
          fontWeight: 500,
          opacity: 0.6,
          letterSpacing: "0.04em",
        }}>
          {tzAbbr}
        </span>
      </div>
    </td>
  );
}

function RegionHeader({ region, colSpan }: { region: string; colSpan: number }) {
  return (
    <tr>
      <td
        colSpan={colSpan}
        style={{
          padding: "10px 14px 6px",
          background: "var(--color-region-bg)",
          borderBottom: "1px solid var(--color-border-subtle)",
          borderLeft: "3px solid var(--color-region-accent)",
        }}
      >
        <span style={{
          fontSize: "0.65rem",
          fontWeight: 700,
          letterSpacing: "0.1em",
          textTransform: "uppercase",
          color: "var(--color-text-muted)",
        }}>
          {region}
        </span>
      </td>
    </tr>
  );
}

function ParkRow({
  park,
  parkIdx,
  weekDates,
  parsedDates,
  parkData,
  rideCounts,
  coastersOnly,
  closingParkIds,
}: {
  park: Park;
  parkIdx: number;
  weekDates: string[];
  parsedDates: ReturnType<typeof parseDate>[];
  parkData: Record<string, DayData>;
  rideCounts?: Record<string, number>;
  coastersOnly?: boolean;
  closingParkIds?: string[];
}) {
  const rowBg = parkIdx % 2 === 0 ? "var(--color-bg)" : "var(--color-surface)";
  const tzAbbr = getTimezoneAbbr(park.timezone);
  const isClosing = closingParkIds?.includes(park.id) ?? false;
  return (
    <tr
      className="park-row"
      data-park={park.name.toLowerCase()}
      style={{ background: rowBg }}
    >
      <td className="sticky-shadow" style={{
        position: "sticky",
        left: 0,
        zIndex: 5,
        padding: 0,
        borderBottom: "1px solid var(--color-border)",
        borderRight: "1px solid var(--color-border)",
        whiteSpace: "nowrap",
        verticalAlign: "middle",
        background: rowBg,
        transition: "background 120ms ease",
      }}>
        <Link href={`/park/${park.id}`} className="park-name-link" style={{
          display: "flex",
          alignItems: "center",
          justifyContent: "space-between",
          padding: "10px 14px",
          gap: 10,
        }}>
          <div>
            <div style={{ display: "flex", alignItems: "center", gap: 6 }}>
              <span style={{ fontWeight: 500, fontSize: "0.85rem", lineHeight: 1.2, color: "var(--color-text)" }}>
                {park.name}
              </span>
              {rideCounts?.[park.id] !== undefined && (
                <span style={{
                  width: 7,
                  height: 7,
                  borderRadius: "50%",
                  background: isClosing ? "var(--color-closing-text)" : "var(--color-open-text)",
                  flexShrink: 0,
                  boxShadow: isClosing
                    ? "0 0 5px var(--color-closing-text)"
                    : "0 0 5px var(--color-open-text)",
                }} />
              )}
            </div>
            <div style={{ fontSize: "0.7rem", color: "var(--color-text-muted)", marginTop: 2 }}>
              {park.location.city}, {park.location.state}
            </div>
          </div>
          {rideCounts?.[park.id] !== undefined && (
            <div style={{ fontSize: "0.72rem", color: isClosing ? "var(--color-closing-hours)" : "var(--color-open-hours)", fontWeight: 600, whiteSpace: "nowrap", flexShrink: 0 }}>
              {rideCounts[park.id]} {coastersOnly
                ? (rideCounts[park.id] === 1 ? "coaster" : "coasters")
                : (rideCounts[park.id] === 1 ? "ride" : "rides")} operating
            </div>
          )}
        </Link>
      </td>

      {weekDates.map((date, i) => (
        <DayCell
          key={date}
          dayData={parkData[date]}
          isWeekend={parsedDates[i].isWeekend}
          tzAbbr={tzAbbr}
        />
      ))}
    </tr>
  );
}

export function WeekCalendar({ parks, weekDates, data, grouped, rideCounts, coastersOnly, closingParkIds }: WeekCalendarProps) {
  const today = getTodayLocal();
  const parsedDates = weekDates.map(parseDate);

  const firstMonth = parsedDates[0].month;
  const firstYear = new Date(weekDates[0] + "T00:00:00").getFullYear();

  // Build ordered list of (region, parks[]) if grouped, otherwise treat all as one group
  const sections: Array<{ region: string | null; parks: Park[] }> = grouped
    ? Array.from(grouped.entries()).map(([region, ps]) => ({ region, parks: ps }))
    : [{ region: null, parks }];

  const colSpan = weekDates.length + 1; // park col + 7 day cols

  return (
    <div style={{ overflowX: "auto", overflowY: "visible" }}>
      <table style={{
        borderCollapse: "collapse",
        width: "100%",
        minWidth: 700,
        tableLayout: "fixed",
      }}>
        <colgroup>
          <col style={{ width: 240 }} />
          {weekDates.map((d) => (
            <col key={d} style={{ width: 130 }} />
          ))}
        </colgroup>

        <thead>
          {/* Month header — only when week crosses a month boundary */}
          {parsedDates.some((d) => d.month !== firstMonth) && (
            <tr>
              <th style={thParkStyle} />
              {weekDates.map((date, i) => {
                const pd = parsedDates[i];
                const showMonth = i === 0 || pd.month !== parsedDates[i - 1].month;
                return (
                  <th key={date} style={{
                    ...thDayStyle,
                    background: pd.isWeekend ? "var(--color-weekend-header)" : "var(--color-bg)",
                    paddingBottom: 0,
                    paddingTop: 8,
                    fontSize: "0.65rem",
                    color: "var(--color-text-muted)",
                    letterSpacing: "0.06em",
                    textTransform: "uppercase",
                    borderBottom: "none",
                  }}>
                    {showMonth ? `${MONTHS[pd.month]} ${new Date(date + "T00:00:00").getFullYear() !== firstYear ? new Date(date + "T00:00:00").getFullYear() : ""}` : ""}
                  </th>
                );
              })}
            </tr>
          )}

          {/* Day header */}
          <tr>
            <th style={thParkStyle}>
              <span style={{ color: "var(--color-text-muted)", fontSize: "0.65rem", letterSpacing: "0.08em", textTransform: "uppercase" }}>
                Park
              </span>
            </th>
            {weekDates.map((date, i) => {
              const pd = parsedDates[i];
              const isToday = date === today;
              return (
                <th key={date} style={{
                  ...thDayStyle,
                  background: isToday
                    ? "var(--color-today-bg)"
                    : pd.isWeekend
                    ? "var(--color-weekend-header)"
                    : "var(--color-bg)",
                  borderBottom: isToday
                    ? "2px solid var(--color-today-border)"
                    : `1px solid var(--color-border)`,
                }}>
                  <div style={{
                    fontSize: "0.65rem",
                    textTransform: "uppercase",
                    letterSpacing: "0.06em",
                    color: isToday ? "var(--color-today-text)" : pd.isWeekend ? "var(--color-text-secondary)" : "var(--color-text-muted)",
                    marginBottom: 2,
                  }}>
                    {DOW[pd.dow]}
                  </div>
                  <div style={{
                    fontSize: "1rem",
                    fontWeight: isToday ? 700 : pd.isWeekend ? 600 : 400,
                    color: isToday ? "var(--color-today-text)" : pd.isWeekend ? "var(--color-text)" : "var(--color-text-muted)",
                  }}>
                    {pd.day}
                  </div>
                </th>
              );
            })}
          </tr>
        </thead>

        <tbody>
          {sections.map(({ region, parks: sectionParks }) => (
            <Fragment key={region ?? "__all__"}>
              {region && (
                <RegionHeader region={region} colSpan={colSpan} />
              )}
              {sectionParks.map((park, parkIdx) => (
                <ParkRow
                  key={park.id}
                  park={park}
                  parkIdx={parkIdx}
                  weekDates={weekDates}
                  parsedDates={parsedDates}
                  parkData={data[park.id] ?? {}}
                  rideCounts={rideCounts}
                  coastersOnly={coastersOnly}
                  closingParkIds={closingParkIds}
                />
              ))}
            </Fragment>
          ))}
        </tbody>
      </table>
    </div>
  );
}

// ── Shared styles ──────────────────────────────────────────────────────────

const thParkStyle: React.CSSProperties = {
  position: "sticky",
  left: 0,
  zIndex: 10,
  padding: "10px 14px",
  textAlign: "left",
  borderBottom: "1px solid var(--color-border)",
  background: "var(--color-bg)",
  verticalAlign: "bottom",
};

const thDayStyle: React.CSSProperties = {
  padding: "10px 8px 8px",
  textAlign: "center",
  fontWeight: 400,
  borderBottom: "1px solid var(--color-border)",
  borderLeft: "1px solid var(--color-border)",
  verticalAlign: "bottom",
};
