import { Button, Divider, Group, Modal, SimpleGrid, Stack, Text, Textarea } from "@mantine/core";
import { DateTimePicker } from "@mantine/dates";
import { useMediaQuery } from "@mantine/hooks";
import { useEffect, useState } from "react";

import type { CheckpointHandlingTimes } from "@/types/trainScheduling";

/** The four station-work stamps, in the order they happen. */
const HANDLING_FIELDS = [
  ["unloadingStartedAt", "Unloading started"],
  ["unloadingCompletedAt", "Unloading finished"],
  ["loadingStartedAt", "Loading started"],
  ["loadingCompletedAt", "Loading finished"],
] as const;

type HandlingField = (typeof HANDLING_FIELDS)[number][0];
type HandlingState = Record<HandlingField, Date | null>;

const EMPTY_HANDLING: HandlingState = {
  unloadingStartedAt: null,
  unloadingCompletedAt: null,
  loadingStartedAt: null,
  loadingCompletedAt: null,
};

/**
 * Time, station work and note for one leg of a train's journey — used both to
 * log a pass (defaults to now) and to correct an already-logged leg
 * (prefilled). Past times are allowed (staff record after the fact); the future
 * is not, and the server additionally keeps legs in corridor order.
 *
 * The four handling stamps are what the loading-and-unloading reports measure:
 * total handling is unloading start to loading end, and whatever is left of the
 * stay is other activity. All four are optional — a stop logged without them
 * still reports its staying time.
 */
export function CheckpointTimeModal({
  opened,
  onClose,
  title,
  icon,
  description,
  initialOccurredAt,
  initialNote,
  initialHandling,
  submitLabel,
  submitColor = "edr-green",
  loading,
  onSubmit,
}: {
  opened: boolean;
  onClose: () => void;
  title: string;
  icon?: React.ReactNode;
  description?: string;
  /** ISO; omit to default to now. */
  initialOccurredAt?: string | null;
  initialNote?: string | null;
  initialHandling?: CheckpointHandlingTimes | null;
  submitLabel: string;
  submitColor?: string;
  loading: boolean;
  onSubmit: (
    values: { occurredAt: string; note: string } & Record<HandlingField, string | null>,
  ) => void;
}) {
  const isSmallScreen = useMediaQuery("(max-width: 48em)");
  const [at, setAt] = useState<Date | null>(null);
  const [note, setNote] = useState("");
  const [handling, setHandling] = useState<HandlingState>(EMPTY_HANDLING);
  useEffect(() => {
    if (!opened) return;
    setAt(initialOccurredAt ? new Date(initialOccurredAt) : new Date());
    setNote(initialNote ?? "");
    setHandling({
      unloadingStartedAt: initialHandling?.unloadingStartedAt
        ? new Date(initialHandling.unloadingStartedAt)
        : null,
      unloadingCompletedAt: initialHandling?.unloadingCompletedAt
        ? new Date(initialHandling.unloadingCompletedAt)
        : null,
      loadingStartedAt: initialHandling?.loadingStartedAt
        ? new Date(initialHandling.loadingStartedAt)
        : null,
      loadingCompletedAt: initialHandling?.loadingCompletedAt
        ? new Date(initialHandling.loadingCompletedAt)
        : null,
    });
  }, [opened, initialOccurredAt, initialNote, initialHandling]);

  return (
    <Modal
      opened={opened}
      onClose={onClose}
      centered
      fullScreen={isSmallScreen}
      radius="lg"
      title={
        <Group gap={8}>
          {icon}
          <Text fw={700}>{title}</Text>
        </Group>
      }
    >
      <Stack gap="md">
        {description ? (
          <Text size="sm" c="dimmed">
            {description}
          </Text>
        ) : null}
        <DateTimePicker
          label="Time"
          description="Defaults to now — pick an earlier time if you are recording after the fact."
          value={at}
          onChange={(v) => setAt(v ? new Date(v) : null)}
          maxDate={new Date()}
          dropdownType={isSmallScreen ? "modal" : "popover"}
          popoverProps={{ withinPortal: true }}
          valueFormat="DD MMM YYYY HH:mm"
          clearable={false}
          radius="md"
        />

        <Divider
          label="Station work (optional)"
          labelPosition="left"
          styles={{ label: { fontWeight: 600 } }}
        />
        <Text size="xs" c="dimmed" mt={-8}>
          Loading and unloading times for this stop. Total handling is unloading start to
          loading finish; the rest of the stay reports as other activity.
        </Text>
        <SimpleGrid cols={{ base: 1, sm: 2 }} spacing="sm">
          {HANDLING_FIELDS.map(([field, label]) => (
            <DateTimePicker
              key={field}
              label={label}
              value={handling[field]}
              onChange={(v) =>
                setHandling((prev) => ({ ...prev, [field]: v ? new Date(v) : null }))
              }
              maxDate={new Date()}
              dropdownType={isSmallScreen ? "modal" : "popover"}
              popoverProps={{ withinPortal: true }}
              valueFormat="DD MMM YYYY HH:mm"
              clearable
              radius="md"
            />
          ))}
        </SimpleGrid>

        <Textarea
          label="Note"
          placeholder="Optional"
          value={note}
          onChange={(e) => setNote(e.currentTarget.value)}
          autosize
          minRows={2}
          maxRows={4}
          maxLength={500}
          radius="md"
        />
        <Group justify="flex-end" gap="sm">
          <Button variant="default" onClick={onClose} disabled={loading}>
            Cancel
          </Button>
          <Button
            color={submitColor}
            loading={loading}
            disabled={!at}
            onClick={() =>
              at &&
              onSubmit({
                occurredAt: at.toISOString(),
                note: note.trim(),
                unloadingStartedAt: handling.unloadingStartedAt?.toISOString() ?? null,
                unloadingCompletedAt: handling.unloadingCompletedAt?.toISOString() ?? null,
                loadingStartedAt: handling.loadingStartedAt?.toISOString() ?? null,
                loadingCompletedAt: handling.loadingCompletedAt?.toISOString() ?? null,
              })
            }
          >
            {submitLabel}
          </Button>
        </Group>
      </Stack>
    </Modal>
  );
}
