import { useEffect, useState } from "react";
import {
  Alert,
  Box,
  Button,
  Group,
  Modal,
  Stack,
  Text,
  TextInput,
  ThemeIcon,
} from "@mantine/core";
import { isAxiosError } from "axios";
import { CalendarClock, Info } from "lucide-react";
import { useMutation } from "@tanstack/react-query";

import { api } from "@/services/api";
import { useToast } from "@/hooks/use-toast";

function parseError(error: unknown, fallback: string): string {
  if (isAxiosError(error)) {
    const message = error.response?.data?.message;
    if (Array.isArray(message)) return message.join(", ");
    if (typeof message === "string") return message;
  }
  return fallback;
}

/** ISO → the `YYYY-MM-DDTHH:mm` value a datetime-local input expects (local time). */
function toLocalInputValue(iso: string | null | undefined): string {
  if (!iso) return "";
  const date = new Date(iso);
  if (Number.isNaN(date.getTime())) return "";
  const pad = (n: number) => String(n).padStart(2, "0");
  return (
    `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}` +
    `T${pad(date.getHours())}:${pad(date.getMinutes())}`
  );
}

export interface EditScheduleDateModalProps {
  scheduleId: string | null;
  currentDate: string | null;
  routeName?: string | null;
  opened: boolean;
  onClose: () => void;
  /** Called after a successful save (e.g. to refetch a list). */
  onSaved?: () => void;
}

/**
 * Reschedule a train's departure date. Only shown for schedules whose booking
 * window has not opened yet; the API rejects a date inside the booking lead
 * window (import/intercity lead in days, export in hours).
 */
export default function EditScheduleDateModal({
  scheduleId,
  currentDate,
  routeName,
  opened,
  onClose,
  onSaved,
}: EditScheduleDateModalProps) {
  const { toast } = useToast();
  const save = useMutation(
    api.trainScheduling.updateScheduleDate.mutationOptions(),
  );

  const [value, setValue] = useState("");
  // Earliest selectable departure, refreshed each time the modal opens.
  const [minValue, setMinValue] = useState("");

  useEffect(() => {
    if (!opened) return;
    setValue(toLocalInputValue(currentDate));
    setMinValue(toLocalInputValue(new Date().toISOString()));
  }, [opened, currentDate]);

  const handleSave = async () => {
    if (!scheduleId || !value) {
      toast({ title: "Pick a departure date", variant: "destructive" });
      return;
    }
    if (new Date(value).getTime() < Date.now()) {
      toast({
        title: "Departure date must be in the future",
        variant: "destructive",
      });
      return;
    }
    try {
      await save.mutateAsync({
        id: scheduleId,
        scheduleDate: new Date(value).toISOString(),
      });
      toast({ title: "Departure date updated" });
      onSaved?.();
      onClose();
    } catch (err) {
      toast({
        title: "Update failed",
        description: parseError(err, "Could not update departure date"),
        variant: "destructive",
      });
    }
  };

  return (
    <Modal
      opened={opened}
      onClose={onClose}
      centered
      radius="lg"
      title={
        <Group gap="sm">
          <ThemeIcon variant="light" color="edr-green" radius="md" size={34}>
            <CalendarClock size={18} />
          </ThemeIcon>
          <Box>
            <Text fw={600} lh={1.2}>
              Edit departure date
            </Text>
            <Text size="xs" c="dimmed" lh={1.2}>
              {routeName ?? "This schedule only"}
            </Text>
          </Box>
        </Group>
      }
    >
      <Stack gap="md">
        <Alert variant="light" color="blue" icon={<Info size={16} />}>
          The date can only be changed before the booking window opens, and must
          still leave room for the booking lead window before departure.
        </Alert>
        <TextInput
          label="Departure date"
          type="datetime-local"
          min={minValue}
          value={value}
          onChange={(e) => setValue(e.currentTarget.value)}
        />
        <Group justify="flex-end" mt="xs">
          <Button variant="default" onClick={onClose} disabled={save.isPending}>
            Cancel
          </Button>
          <Button onClick={handleSave} loading={save.isPending}>
            Save
          </Button>
        </Group>
      </Stack>
    </Modal>
  );
}
