import { Box, Button, Group, Text } from "@mantine/core";
import {
  Calendar as CalendarIcon,
  Check,
  ChevronLeft,
  ChevronRight,
} from "lucide-react";
import { useMemo, useState } from "react";

export interface OperationDatePickerProps {
  /** Selectable days as `yyyy-MM-dd` strings. */
  availableDays: string[];
  /** Show the loading state instead of the grid. */
  isLoading?: boolean;
  /** Currently selected day as `yyyy-MM-dd`, or "" when none. */
  value: string;
  /** Called with the picked `yyyy-MM-dd` day. */
  onChange: (date: string) => void;
  /** Stretch to the full width of the parent container. */
  fullWidth?: boolean;
}

/** `yyyy-MM-dd` for a local date. */
function fmtDay(d: Date): string {
  const y = d.getFullYear();
  const m = String(d.getMonth() + 1).padStart(2, "0");
  const day = String(d.getDate()).padStart(2, "0");
  return `${y}-${m}-${day}`;
}

const MONTH_NAMES = [
  "January",
  "February",
  "March",
  "April",
  "May",
  "June",
  "July",
  "August",
  "September",
  "October",
  "November",
  "December",
];

const WEEKDAY_LABELS = ["MON", "TUE", "WED", "THU", "FRI", "SAT", "SUN"];

/**
 * Presentational month calendar for picking a binding shipment day. Only the
 * `availableDays` (passed in by the caller, which owns the query) are
 * selectable; every other day is disabled. Framework-light: no data fetching,
 * no date library — both the portal and backoffice feed it their own
 * availability results so the picker renders identically in each app.
 */
export function OperationDatePicker({
  availableDays,
  isLoading = false,
  value,
  onChange,
  fullWidth = false,
}: OperationDatePickerProps) {
  const [month, setMonth] = useState(() => {
    const now = new Date();
    return new Date(now.getFullYear(), now.getMonth(), 1);
  });

  const departureDays = useMemo(
    () => new Set(availableDays ?? []),
    [availableDays],
  );

  const cells = useMemo(() => {
    const first = new Date(month.getFullYear(), month.getMonth(), 1);
    const lead = (first.getDay() + 6) % 7;
    const start = new Date(first);
    start.setDate(first.getDate() - lead);

    const today = new Date();
    const todayStr = fmtDay(today);

    return Array.from({ length: 42 }, (_, i) => {
      const date = new Date(start);
      date.setDate(start.getDate() + i);
      const dateString = fmtDay(date);
      return {
        dateString,
        day: date.getDate(),
        inMonth: date.getMonth() === month.getMonth(),
        today: dateString === todayStr,
        selected: value === dateString,
        hasDeparture: departureDays.has(dateString),
      };
    });
  }, [month, departureDays, value]);

  const availableInMonth = useMemo(
    () => cells.filter((c) => c.inMonth && c.hasDeparture).length,
    [cells],
  );

  const shiftMonth = (delta: number) =>
    setMonth((m) => new Date(m.getFullYear(), m.getMonth() + delta, 1));

  return (
    <Box
      style={{
        border: "1px solid #E6ECF2",
        borderRadius: 12,
        padding: fullWidth ? "12px 16px" : 14,
        width: fullWidth ? "100%" : undefined,
        maxWidth: fullWidth ? undefined : 340,
      }}
    >
      <Group
        justify="space-between"
        align="center"
        mb="sm"
        px={fullWidth ? 4 : 0}
        style={
          fullWidth
            ? {
                borderBottom: "1px solid #EEF2F6",
                paddingBottom: 10,
              }
            : undefined
        }
      >
        <Button
          variant="default"
          size="xs"
          px={6}
          radius="xl"
          onClick={() => shiftMonth(-1)}
        >
          <ChevronLeft size={15} />
        </Button>
        <StackedMonthHeader month={month} availableCount={availableInMonth} />
        <Button
          variant="default"
          size="xs"
          px={6}
          radius="xl"
          onClick={() => shiftMonth(1)}
        >
          <ChevronRight size={15} />
        </Button>
      </Group>

      {isLoading ? (
        <Group justify="center" py="md" gap={8}>
          <CalendarIcon size={15} color="#9AA8B5" />
          <Text fz="12px" c="dimmed">
            Loading available days…
          </Text>
        </Group>
      ) : (
        <>
          <Box
            style={{
              display: "grid",
              gridTemplateColumns: "repeat(7, 1fr)",
              gap: 4,
              marginBottom: 6,
            }}
          >
            {WEEKDAY_LABELS.map((d) => (
              <Text key={d} ta="center" fz="10px" fw={700} c="#9AA8B5">
                {d}
              </Text>
            ))}
          </Box>
          <Box
            style={{
              display: "grid",
              gridTemplateColumns: "repeat(7, 1fr)",
              gap: 4,
            }}
          >
            {cells.map((c) => {
              const clickable = c.hasDeparture && c.inMonth;
              return (
                <button
                  key={c.dateString}
                  type="button"
                  disabled={!clickable}
                  onClick={() => clickable && onChange(c.dateString)}
                  style={{
                    position: "relative",
                    height: 34,
                    borderRadius: 8,
                    fontSize: 12.5,
                    fontWeight: c.selected ? 800 : 600,
                    cursor: clickable ? "pointer" : "default",
                    border: c.selected
                      ? "1.5px solid #12B981"
                      : c.today
                        ? "1.5px solid #94A3B8"
                        : clickable
                          ? "1px solid #CDEBDD"
                          : "1px solid transparent",
                    background: c.selected
                      ? "#12B981"
                      : clickable
                        ? "#F4FBF7"
                        : "transparent",
                    color: c.selected
                      ? "#fff"
                      : !c.inMonth
                        ? "#CBD5E1"
                        : clickable
                          ? "#0A6F4D"
                          : "#C4CDD6",
                    transition: "all 120ms ease",
                  }}
                >
                  {c.day}
                  {c.hasDeparture && c.inMonth && !c.selected && (
                    <span
                      style={{
                        position: "absolute",
                        bottom: 4,
                        left: "50%",
                        transform: "translateX(-50%)",
                        width: 4,
                        height: 4,
                        borderRadius: "50%",
                        background: "#12B981",
                      }}
                    />
                  )}
                  {c.selected && (
                    <Check
                      size={11}
                      color="#fff"
                      strokeWidth={3}
                      style={{
                        position: "absolute",
                        bottom: 3,
                        left: "50%",
                        transform: "translateX(-50%)",
                      }}
                    />
                  )}
                </button>
              );
            })}
          </Box>
          {value && (
            <Group
              justify="center"
              mt="sm"
              py={6}
              px={10}
              style={{
                borderRadius: 8,
                background: "#F4FBF7",
                border: "1px solid #CDEBDD",
              }}
            >
              <Text fz="12px" c="#0A6F4D" fw={600}>
                Selected:{" "}
                {new Date(value + "T00:00:00").toLocaleDateString(undefined, {
                  weekday: "short",
                  month: "short",
                  day: "numeric",
                  year: "numeric",
                })}
              </Text>
            </Group>
          )}
          {departureDays.size === 0 && (
            <Text fz="12px" c="orange.7" mt="sm" ta="center">
              No scheduled departures found for this route yet.
            </Text>
          )}
        </>
      )}
    </Box>
  );
}

function StackedMonthHeader({
  month,
  availableCount,
}: {
  month: Date;
  availableCount: number;
}) {
  return (
    <Box style={{ textAlign: "center" }}>
      <Text fz="14px" fw={800} c="#10202F" lh={1.2}>
        {MONTH_NAMES[month.getMonth()]} {month.getFullYear()}
      </Text>
      <Text fz="11px" c="#64748B" mt={2}>
        {availableCount} available day{availableCount === 1 ? "" : "s"}
      </Text>
    </Box>
  );
}

export default OperationDatePicker;
