"use client";

import React, { useCallback, useEffect, useMemo, useState } from "react";
import {
  ActionIcon,
  Alert,
  Badge,
  Box,
  Button,
  Center,
  Checkbox,
  Container,
  Divider,
  Drawer,
  Group,
  Menu,
  Modal,
  NumberInput,
  Paper,
  SegmentedControl,
  Select,
  SimpleGrid,
  Skeleton,
  Stack,
  Switch,
  Table,
  Text,
  Textarea,
  ThemeIcon,
  Title,
  Tooltip,
} from "@mantine/core";
import { DatePickerInput } from "@mantine/dates";
import { useDisclosure } from "@mantine/hooks";
import { notifications } from "@mantine/notifications";
import {
  IconAlertCircle,
  IconArrowLeft,
  IconArrowRight,
  IconCalendarEvent,
  IconCalendarStats,
  IconCircleCheck,
  IconDotsVertical,
  IconEdit,
  IconFileImport,
  IconMapPin,
  IconPlus,
  IconRefresh,
  IconRoute,
  IconTrash,
  IconUsersGroup,
  IconX,
} from "@tabler/icons-react";
import dayjs from "dayjs";
import { useNavigate } from "react-router";
import { searchDestinationItineraries } from "@/lib/features/destination/itineraries/query";
import {
  addDestinationItineraries,
  deleteDestinationItinerary,
  updateDestinationItinerary,
} from "@/lib/features/destination/itineraries/action";
import { findItineraryDestination } from "@/lib/features/destination/itineraries/config";
import type { DestinationItinerary } from "@/lib/features/destination/itineraries/types";
import type { Resort } from "@/lib/features/resorts/types";
import type { AccessScope } from "@/lib/features/types";
import { ScheduleImportModal } from "./_components/ScheduleImportModal";

interface Props {
  resort: Resort | null;
  accessScope: AccessScope;
  initialError?: string;
}

type StatusFilter = "all" | "upcoming" | "ongoing" | "ended" | "inactive";
type Timing = "upcoming" | "ongoing" | "ended";

type ItineraryForm = {
  content_id: string | null;
  range: [string | null, string | null];
  max_bookable_units: number | "";
  comment: string;
  is_active: boolean;
};

const DEFAULT_UNITS = 2;

const EMPTY_FORM: ItineraryForm = {
  content_id: null,
  range: [null, null],
  max_bookable_units: DEFAULT_UNITS,
  comment: "",
  is_active: true,
};

const FONT = { fontFamily: "Outfit, Inter, sans-serif" };
const CONTENT_COLORS = ["teal", "indigo", "grape", "orange", "cyan", "pink"];

const toDateOnly = (v: string | null) => (v ? dayjs(v).format("YYYY-MM-DD") : null);
const fmt = (v: string | null) => (v ? dayjs(v).format("DD MMM YYYY") : "—");
const nights = (from: string | null, to: string | null) =>
  from && to ? Math.max(0, dayjs(to).diff(dayjs(from), "day")) : 0;

// PATCH sends the full record, matching the Updot contract, with overrides on top.
function patchBody(it: DestinationItinerary, overrides: { is_active?: boolean } = {}) {
  return {
    content_id: it.content_id,
    available_from: toDateOnly(it.available_from) ?? undefined,
    available_to: toDateOnly(it.available_to) ?? undefined,
    max_bookable_units: it.max_bookable_units,
    comment: it.comment ?? "",
    is_active: it.is_active ?? true,
    ...overrides,
  };
}

function timingOf(it: DestinationItinerary): Timing {
  const today = dayjs().startOf("day");
  if (it.available_from && dayjs(it.available_from).isAfter(today)) return "upcoming";
  if (it.available_to && dayjs(it.available_to).isBefore(today)) return "ended";
  return "ongoing";
}

function timingBadge(it: DestinationItinerary) {
  const t = timingOf(it);
  if (t === "upcoming") {
    const days = dayjs(it.available_from).startOf("day").diff(dayjs().startOf("day"), "day");
    return (
      <Badge variant="light" color="blue" size="sm">
        Starts in {days} day{days === 1 ? "" : "s"}
      </Badge>
    );
  }
  if (t === "ongoing") {
    return (
      <Badge variant="light" color="green" size="sm">
        Ongoing
      </Badge>
    );
  }
  return (
    <Badge variant="light" color="gray" size="sm">
      Ended
    </Badge>
  );
}

function StatCard({
  label,
  value,
  hint,
  color,
  icon,
  loading,
}: {
  label: string;
  value: number;
  hint: string;
  color: string;
  icon: React.ReactNode;
  loading: boolean;
}) {
  return (
    <Paper withBorder radius="lg" p="md" style={{ borderTop: `3px solid var(--mantine-color-${color}-6)` }}>
      <Group justify="space-between" align="flex-start" wrap="nowrap">
        <Stack gap={2}>
          <Text size="xs" c="dimmed" fw={600} tt="uppercase">
            {label}
          </Text>
          {loading ? (
            <Skeleton height={30} width={50} mt={4} />
          ) : (
            <Text fz={28} fw={700} lh={1.2} style={FONT}>
              {value}
            </Text>
          )}
          <Text size="xs" c="dimmed">
            {hint}
          </Text>
        </Stack>
        <ThemeIcon variant="light" color={color} size={40} radius="md">
          {icon}
        </ThemeIcon>
      </Group>
    </Paper>
  );
}

export default function ResortItinerariesClientPage({ resort, accessScope, initialError }: Props) {
  const navigate = useNavigate();
  const destination = resort ? findItineraryDestination(resort) : undefined;
  const destinationId = destination?.destinationId ?? "";
  const slug = destination?.slug ?? "";
  const contentOptions = useMemo(() => destination?.contentOptions ?? [], [destination]);

  const [itineraries, setItineraries] = useState<DestinationItinerary[]>([]);
  const [loading, setLoading] = useState(true);
  const [loadError, setLoadError] = useState<string | null>(null);

  const [statusFilter, setStatusFilter] = useState<StatusFilter>("all");
  const [contentFilter, setContentFilter] = useState<string | null>(null);

  const [editing, setEditing] = useState<DestinationItinerary | null>(null);
  // One entry when editing; one or more when adding (saved in a single batch).
  const [forms, setForms] = useState<ItineraryForm[]>([EMPTY_FORM]);
  const [saving, setSaving] = useState(false);
  const [drawerOpened, { open: openDrawer, close: closeDrawer }] = useDisclosure(false);

  const [deleteTarget, setDeleteTarget] = useState<DestinationItinerary | null>(null);
  const [deleting, setDeleting] = useState(false);
  const [togglingId, setTogglingId] = useState<string | null>(null);

  const [selected, setSelected] = useState<Set<string>>(new Set());
  const [bulkBusy, setBulkBusy] = useState(false);
  const [bulkDeleteOpen, setBulkDeleteOpen] = useState(false);
  const [importOpened, { open: openImport, close: closeImport }] = useDisclosure(false);


  const contentLabel = useCallback(
    (it: DestinationItinerary) =>
      contentOptions.find((o) => o.value === it.content_id)?.label || it.name || it.content_id,
    [contentOptions],
  );
  const contentColor = (contentId: string) => {
    const idx = contentOptions.findIndex((o) => o.value === contentId);
    return CONTENT_COLORS[(idx < 0 ? 0 : idx) % CONTENT_COLORS.length];
  };

  const load = useCallback(async () => {
    if (!destinationId) {
      setLoading(false);
      return;
    }
    setLoading(true);
    setLoadError(null);
    try {
      const res = await searchDestinationItineraries(destinationId, slug);
      if (res.success) {
        const rows = Array.isArray(res.data) ? res.data.filter((i) => !i.is_deleted) : [];
        rows.sort((a, b) => dayjs(a.available_from).valueOf() - dayjs(b.available_from).valueOf());
        setItineraries(rows);
        setSelected(new Set());
      } else {
        setLoadError(res.message || "Failed to load itineraries");
      }
    } catch {
      setLoadError("Failed to load itineraries");
    } finally {
      setLoading(false);
    }
  }, [destinationId, slug]);

  useEffect(() => {
    load();
  }, [load]);

  const stats = useMemo(() => {
    const active = itineraries.filter((i) => i.is_active);
    return {
      total: itineraries.length,
      active: active.length,
      upcoming: active.filter((i) => timingOf(i) === "upcoming").length,
      units: active
        .filter((i) => timingOf(i) !== "ended")
        .reduce((sum, i) => sum + (Number(i.max_bookable_units) || 0), 0),
    };
  }, [itineraries]);

  const filtered = useMemo(
    () =>
      itineraries.filter((it) => {
        if (contentFilter && it.content_id !== contentFilter) return false;
        if (statusFilter === "all") return true;
        if (statusFilter === "inactive") return !it.is_active;
        return it.is_active && timingOf(it) === statusFilter;
      }),
    [itineraries, statusFilter, contentFilter],
  );

  const canManage = accessScope.update || accessScope.delete;

  const handleAdd = () => {
    setEditing(null);
    setForms([EMPTY_FORM]);
    openDrawer();
  };

  const handleEdit = (it: DestinationItinerary) => {
    setEditing(it);
    setForms([{
      content_id: it.content_id ?? null,
      range: [toDateOnly(it.available_from), toDateOnly(it.available_to)],
      max_bookable_units: it.max_bookable_units ?? DEFAULT_UNITS,
      comment: it.comment ?? "",
      is_active: it.is_active ?? true,
    }]);
    openDrawer();
  };

  const updateForm = (idx: number, patch: Partial<ItineraryForm>) =>
    setForms((prev) => prev.map((f, i) => (i === idx ? { ...f, ...patch } : f)));

  // New row inherits the previous itinerary and unit count, and its window
  // starts where the previous one ends, so back-to-back windows are one click.
  const addFormRow = () =>
    setForms((prev) => {
      const last = prev[prev.length - 1];
      const len = last.range[0] && last.range[1] ? nights(last.range[0], last.range[1]) : 7;
      const start = last.range[1];
      return [
        ...prev,
        {
          ...EMPTY_FORM,
          content_id: last.content_id,
          max_bookable_units: last.max_bookable_units,
          range: start ? [start, dayjs(start).add(len || 7, "day").format("YYYY-MM-DD")] : [null, null],
        },
      ];
    });

  const removeFormRow = (idx: number) => setForms((prev) => prev.filter((_, i) => i !== idx));

  const handleSubmit = async () => {
    const invalid = forms.findIndex(
      (f) => !f.content_id || !f.range[0] || !f.range[1] || f.max_bookable_units === "",
    );
    if (invalid >= 0) {
      notifications.show({
        color: "red",
        message: `${forms.length > 1 ? `Itinerary ${invalid + 1}: ` : ""}itinerary, date range and max bookable units are required`,
      });
      return;
    }

    setSaving(true);
    try {
      const items = forms.map((f) => ({
        content_id: f.content_id!,
        available_from: f.range[0]!,
        available_to: f.range[1]!,
        max_bookable_units: Number(f.max_bookable_units),
      }));
      const res = editing?.id
        ? await updateDestinationItinerary({
          ...items[0],
          destination_id: destinationId,
          id: editing.id,
          comment: forms[0].comment,
          is_active: forms[0].is_active,
        })
        : await addDestinationItineraries(
          destinationId,
          items.map((item, i) => ({ ...item, comments: forms[i].comment })),
        );

      if (res.success) {
        notifications.show({
          color: "green",
          message: editing
            ? "Itinerary updated"
            : `${items.length} itinerar${items.length === 1 ? "y" : "ies"} added`,
        });
        closeDrawer();
        load();
      } else {
        notifications.show({ color: "red", message: res.message || "Save failed" });
      }
    } catch {
      notifications.show({ color: "red", message: "Save failed" });
    } finally {
      setSaving(false);
    }
  };

  const handleToggleActive = async (it: DestinationItinerary, isActive: boolean) => {
    if (!it.id) return;
    setTogglingId(it.id);
    try {
      const res = await updateDestinationItinerary({
        destination_id: destinationId,
        id: it.id,
        ...patchBody(it, { is_active: isActive }),
      });
      if (res.success) {
        setItineraries((prev) => prev.map((row) => (row.id === it.id ? { ...row, is_active: isActive } : row)));
        notifications.show({ color: "green", message: isActive ? "Itinerary activated" : "Itinerary deactivated" });
      } else {
        notifications.show({ color: "red", message: res.message || "Update failed" });
      }
    } catch {
      notifications.show({ color: "red", message: "Update failed" });
    } finally {
      setTogglingId(null);
    }
  };

  const handleDelete = async () => {
    if (!deleteTarget?.id) return;
    setDeleting(true);
    try {
      const res = await deleteDestinationItinerary({ destination_id: destinationId, id: deleteTarget.id });
      if (res.success) {
        notifications.show({ color: "green", message: "Itinerary deleted" });
        setDeleteTarget(null);
        load();
      } else {
        notifications.show({ color: "red", message: res.message || "Delete failed" });
      }
    } catch {
      notifications.show({ color: "red", message: "Delete failed" });
    } finally {
      setDeleting(false);
    }
  };

  const selectedRows = itineraries.filter((it) => it.id && selected.has(it.id));
  const visibleIds = filtered.map((it) => it.id).filter((id): id is string => !!id);
  const allVisibleSelected = visibleIds.length > 0 && visibleIds.every((id) => selected.has(id));
  const someVisibleSelected = visibleIds.some((id) => selected.has(id));

  const toggleRow = (id: string, checked: boolean) =>
    setSelected((prev) => {
      const next = new Set(prev);
      if (checked) next.add(id);
      else next.delete(id);
      return next;
    });
  const toggleAllVisible = (checked: boolean) =>
    setSelected((prev) => {
      const next = new Set(prev);
      visibleIds.forEach((id) => (checked ? next.add(id) : next.delete(id)));
      return next;
    });

  // No bulk endpoint upstream, so run one request per row, sequentially.
  const runBulk = async (label: string, fn: (it: DestinationItinerary) => Promise<{ success: boolean }>) => {
    setBulkBusy(true);
    let ok = 0;
    let failed = 0;
    for (const it of selectedRows) {
      try {
        const r = await fn(it);
        if (r.success) ok++;
        else failed++;
      } catch {
        failed++;
      }
    }
    setBulkBusy(false);
    notifications.show({
      color: failed ? (ok ? "yellow" : "red") : "green",
      message: `${label}: ${ok} done${failed ? `, ${failed} failed` : ""}`,
    });
    load();
  };

  const bulkSetActive = (isActive: boolean) =>
    runBulk(isActive ? "Activated" : "Deactivated", (it) =>
      updateDestinationItinerary({ destination_id: destinationId, id: it.id!, ...patchBody(it, { is_active: isActive }) }),
    );

  const bulkDelete = async () => {
    await runBulk("Deleted", (it) => deleteDestinationItinerary({ destination_id: destinationId, id: it.id! }));
    setBulkDeleteOpen(false);
  };


  return (
    <Container fluid px="xl" py="xl">
      {/* Header */}
      <Group justify="space-between" mb="lg" align="flex-start">
        <Stack gap={6}>
          <Button
            variant="subtle"
            size="compact-sm"
            leftSection={<IconArrowLeft size={14} />}
            onClick={() => navigate(resort ? `/admin/resorts/${resort.id}` : "/admin/resorts")}
            style={{ ...FONT, fontWeight: 600, alignSelf: "flex-start" }}
          >
            Back to resort
          </Button>
          <Group gap="sm">
            <ThemeIcon variant="gradient" gradient={{ from: "teal", to: "blue", deg: 135 }} size={44} radius="md">
              <IconRoute size={24} />
            </ThemeIcon>
            <Stack gap={0}>
              <Title order={2} style={{ ...FONT, fontWeight: 700 }}>
                Itineraries
              </Title>
              <Group gap={6}>
                <IconMapPin size={14} color="var(--mantine-color-dimmed)" />
                <Text size="sm" c="dimmed">
                  {resort?.name ?? "Unknown resort"}
                </Text>
                {slug && (
                  <Badge variant="outline" color="gray" size="xs">
                    {slug}
                  </Badge>
                )}
              </Group>
            </Stack>
          </Group>
        </Stack>
        {destinationId && (
          <Group>
            <Tooltip label="Refresh">
              <ActionIcon variant="light" color="gray" size="lg" onClick={load} loading={loading}>
                <IconRefresh size={18} />
              </ActionIcon>
            </Tooltip>
            {accessScope.create && (
              <>
                <Button variant="light" color="teal" leftSection={<IconFileImport size={16} />} onClick={openImport}>
                  Import schedule
                </Button>
                <Button leftSection={<IconPlus size={16} />} onClick={handleAdd}>
                  Add Itinerary
                </Button>
              </>
            )}
          </Group>
        )}
      </Group>

      {initialError && (
        <Alert color="red" icon={<IconAlertCircle size={16} />} mb="lg">
          {initialError}
        </Alert>
      )}

      {resort && !destination && (
        <Alert color="yellow" icon={<IconAlertCircle size={16} />} mb="lg">
          This resort does not use the itinerary booking flow.
        </Alert>
      )}

      {destinationId && (
        <Stack gap="lg">
          {/* KPIs */}
          <SimpleGrid cols={{ base: 1, xs: 2, lg: 4 }} spacing="md">
            <StatCard
              label="Total"
              value={stats.total}
              hint="All itinerary windows"
              color="indigo"
              icon={<IconRoute size={20} />}
              loading={loading}
            />
            <StatCard
              label="Active"
              value={stats.active}
              hint="Bookable by members"
              color="green"
              icon={<IconCircleCheck size={20} />}
              loading={loading}
            />
            <StatCard
              label="Upcoming"
              value={stats.upcoming}
              hint="Active, not started yet"
              color="blue"
              icon={<IconCalendarEvent size={20} />}
              loading={loading}
            />
            <StatCard
              label="Bookable units"
              value={stats.units}
              hint="Across active, open windows"
              color="orange"
              icon={<IconUsersGroup size={20} />}
              loading={loading}
            />
          </SimpleGrid>

          {loadError && (
            <Alert color="red" icon={<IconAlertCircle size={16} />}>
              {loadError}
            </Alert>
          )}


          {/* List */}
          <Paper withBorder radius="lg" p={0} style={{ overflow: "hidden" }}>
            {selectedRows.length > 0 && (
              <Group justify="space-between" px="md" py="sm" bg="var(--mantine-color-blue-0)" wrap="wrap" gap="sm">
                <Group gap="xs">
                  <Badge color="blue" variant="filled" size="lg" radius="sm">
                    {selectedRows.length}
                  </Badge>
                  <Text size="sm" fw={600}>
                    selected
                  </Text>
                  <Button size="compact-xs" variant="subtle" leftSection={<IconX size={12} />} onClick={() => setSelected(new Set())}>
                    Clear
                  </Button>
                </Group>
                <Group gap="xs">
                  {accessScope.update && (
                    <>
                      <Button size="xs" variant="light" color="green" loading={bulkBusy} onClick={() => bulkSetActive(true)}>
                        Activate
                      </Button>
                      <Button size="xs" variant="light" color="gray" loading={bulkBusy} onClick={() => bulkSetActive(false)}>
                        Deactivate
                      </Button>
                    </>
                  )}
                  {accessScope.delete && (
                    <Button
                      size="xs"
                      variant="light"
                      color="red"
                      leftSection={<IconTrash size={14} />}
                      disabled={bulkBusy}
                      onClick={() => setBulkDeleteOpen(true)}
                    >
                      Delete
                    </Button>
                  )}
                </Group>
              </Group>
            )}
            <Group justify="space-between" p="md" wrap="wrap" gap="sm">
              <SegmentedControl
                size="xs"
                radius="md"
                value={statusFilter}
                onChange={(v) => setStatusFilter(v as StatusFilter)}
                data={[
                  { value: "all", label: "All" },
                  { value: "upcoming", label: "Upcoming" },
                  { value: "ongoing", label: "Ongoing" },
                  { value: "ended", label: "Ended" },
                  { value: "inactive", label: "Inactive" },
                ]}
              />
              <Select
                size="xs"
                placeholder="All itineraries"
                data={contentOptions}
                value={contentFilter}
                onChange={setContentFilter}
                clearable
                w={220}
              />
            </Group>
            <Divider />

            {loading ? (
              <Stack p="md" gap="sm">
                {[0, 1, 2].map((i) => (
                  <Skeleton key={i} height={44} radius="sm" />
                ))}
              </Stack>
            ) : filtered.length === 0 ? (
              <Center py={60}>
                <Stack align="center" gap="xs">
                  <ThemeIcon variant="light" color="gray" size={56} radius="xl">
                    <IconCalendarStats size={28} />
                  </ThemeIcon>
                  <Text fw={600} style={FONT}>
                    {itineraries.length === 0 ? "No itineraries yet" : "No itineraries match these filters"}
                  </Text>
                  <Text size="sm" c="dimmed">
                    {itineraries.length === 0
                      ? "Add an itinerary window to open it for member bookings."
                      : "Try a different status or itinerary."}
                  </Text>
                  {itineraries.length === 0 && accessScope.create && (
                    <Button mt="xs" variant="light" leftSection={<IconPlus size={16} />} onClick={handleAdd}>
                      Add Itinerary
                    </Button>
                  )}
                </Stack>
              </Center>
            ) : (
              <Table.ScrollContainer minWidth={900}>
                <Table verticalSpacing="sm" horizontalSpacing="md" highlightOnHover style={FONT}>
                  <Table.Thead bg="var(--mantine-color-gray-0)">
                    <Table.Tr>
                      {canManage && (
                        <Table.Th w={40}>
                          <Checkbox
                            aria-label="Select all"
                            checked={allVisibleSelected}
                            indeterminate={someVisibleSelected && !allVisibleSelected}
                            onChange={(e) => toggleAllVisible(e.currentTarget.checked)}
                          />
                        </Table.Th>
                      )}
                      <Table.Th>Itinerary</Table.Th>
                      <Table.Th>Availability</Table.Th>
                      <Table.Th>Timing</Table.Th>
                      <Table.Th ta="center">Max units</Table.Th>
                      <Table.Th>Comment</Table.Th>
                      <Table.Th>Active</Table.Th>
                      {canManage && <Table.Th w={60} />}
                    </Table.Tr>
                  </Table.Thead>
                  <Table.Tbody>
                    {filtered.map((it) => (
                      <Table.Tr
                        key={it.id ?? `${it.content_id}-${it.available_from}`}
                        opacity={it.is_active ? 1 : 0.6}
                        bg={it.id && selected.has(it.id) ? "var(--mantine-color-blue-light)" : undefined}
                      >
                        {canManage && (
                          <Table.Td>
                            <Checkbox
                              aria-label="Select itinerary"
                              checked={!!it.id && selected.has(it.id)}
                              disabled={!it.id}
                              onChange={(e) => it.id && toggleRow(it.id, e.currentTarget.checked)}
                            />
                          </Table.Td>
                        )}
                        <Table.Td>
                          <Group gap="sm" wrap="nowrap">
                            <ThemeIcon variant="light" color={contentColor(it.content_id)} radius="md">
                              <IconRoute size={16} />
                            </ThemeIcon>
                            <Stack gap={0}>
                              <Text fw={600} size="sm">
                                {contentLabel(it)}
                              </Text>
                              {it.id && (
                                <Text size="xs" c="dimmed">
                                  #{it.id}
                                </Text>
                              )}
                            </Stack>
                          </Group>
                        </Table.Td>
                        <Table.Td>
                          <Group gap={6} wrap="nowrap">
                            <Text size="sm">{fmt(it.available_from)}</Text>
                            <IconArrowRight size={14} color="var(--mantine-color-dimmed)" />
                            <Text size="sm">{fmt(it.available_to)}</Text>
                          </Group>
                          <Text size="xs" c="dimmed">
                            {nights(it.available_from, it.available_to)} nights
                          </Text>
                        </Table.Td>
                        <Table.Td>{timingBadge(it)}</Table.Td>
                        <Table.Td ta="center">
                          <Badge variant="default" size="lg" radius="sm">
                            {it.max_bookable_units}
                          </Badge>
                        </Table.Td>
                        <Table.Td maw={260}>
                          {it.comment ? (
                            <Tooltip label={it.comment} multiline w={280} withArrow>
                              <Text size="sm" lineClamp={1}>
                                {it.comment}
                              </Text>
                            </Tooltip>
                          ) : (
                            <Text size="sm" c="dimmed">
                              —
                            </Text>
                          )}
                        </Table.Td>
                        <Table.Td>
                          <Switch
                            checked={!!it.is_active}
                            disabled={!accessScope.update || togglingId === it.id}
                            onChange={(e) => handleToggleActive(it, e.currentTarget.checked)}
                            color="green"
                          />
                        </Table.Td>
                        {canManage && (
                          <Table.Td>
                            <Menu position="bottom-end" withinPortal shadow="md">
                              <Menu.Target>
                                <ActionIcon variant="subtle" color="gray" aria-label="Itinerary actions">
                                  <IconDotsVertical size={16} />
                                </ActionIcon>
                              </Menu.Target>
                              <Menu.Dropdown>
                                {accessScope.update && (
                                  <Menu.Item leftSection={<IconEdit size={14} />} onClick={() => handleEdit(it)}>
                                    Edit
                                  </Menu.Item>
                                )}
                                {accessScope.delete && (
                                  <Menu.Item
                                    color="red"
                                    leftSection={<IconTrash size={14} />}
                                    onClick={() => setDeleteTarget(it)}
                                  >
                                    Delete
                                  </Menu.Item>
                                )}
                              </Menu.Dropdown>
                            </Menu>
                          </Table.Td>
                        )}
                      </Table.Tr>
                    ))}
                  </Table.Tbody>
                </Table>
              </Table.ScrollContainer>
            )}
          </Paper>
        </Stack>
      )}

      {/* Add / edit drawer */}
      <Drawer
        opened={drawerOpened}
        onClose={closeDrawer}
        position="right"
        size={forms.length > 1 ? "lg" : "md"}
        title={
          <Group gap="sm">
            <ThemeIcon variant="light" color="teal" radius="md">
              {editing ? <IconEdit size={16} /> : <IconPlus size={16} />}
            </ThemeIcon>
            <Text fw={700} style={FONT}>
              {editing ? "Edit Itinerary" : "Add Itinerary"}
            </Text>
          </Group>
        }
      >
        <Stack gap="md">
          {forms.map((form, idx) => {
            const formNights = nights(form.range[0], form.range[1]);
            const fields = (
              <Stack gap="md">
                <Select
                  label="Itinerary"
                  description={idx === 0 ? "Transfer / route content shown to members" : undefined}
                  placeholder="Select itinerary"
                  data={contentOptions}
                  value={form.content_id}
                  onChange={(v) => updateForm(idx, { content_id: v })}
                  required
                />
                <DatePickerInput
                  type="range"
                  label="Availability window"
                  description={idx === 0 ? "Dates members can book this itinerary" : undefined}
                  placeholder="Pick start and end dates"
                  valueFormat="DD MMM YYYY"
                  value={form.range}
                  onChange={(v) => updateForm(idx, { range: v as [string | null, string | null] })}
                  leftSection={<IconCalendarEvent size={16} />}
                  allowSingleDateInRange
                  required
                />
                {form.range[0] && form.range[1] && (
                  <Box
                    p="sm"
                    style={{
                      borderRadius: "var(--mantine-radius-md)",
                      background: "var(--mantine-color-teal-0)",
                    }}
                  >
                    <Text size="sm" c="teal.8">
                      {fmt(form.range[0])} → {fmt(form.range[1])} · {formNights} night{formNights === 1 ? "" : "s"}
                    </Text>
                  </Box>
                )}
                <NumberInput
                  label="Max bookable units"
                  description={idx === 0 ? "How many units can be booked in this window" : undefined}
                  min={1}
                  value={form.max_bookable_units}
                  onChange={(v) => updateForm(idx, { max_bookable_units: v === "" ? "" : Number(v) })}
                  required
                />
                <Textarea
                  label="Comment"
                  placeholder="Internal note (optional)"
                  value={form.comment}
                  onChange={(e) => updateForm(idx, { comment: e.currentTarget.value })}
                  minRows={2}
                  autosize
                />
                {editing && (
                  <Paper withBorder radius="md" p="sm">
                    <Switch
                      label="Active"
                      description="Inactive itineraries are hidden from members"
                      checked={form.is_active}
                      color="green"
                      onChange={(e) => updateForm(idx, { is_active: e.currentTarget.checked })}
                    />
                  </Paper>
                )}
              </Stack>
            );

            if (editing || forms.length === 1) return <React.Fragment key={idx}>{fields}</React.Fragment>;

            return (
              <Paper key={idx} withBorder radius="md" p="md" style={{ borderLeft: "3px solid var(--mantine-color-teal-5)" }}>
                <Group justify="space-between" mb="sm">
                  <Badge variant="light" color="teal">
                    Itinerary {idx + 1}
                  </Badge>
                  <Tooltip label="Remove">
                    <ActionIcon variant="subtle" color="red" onClick={() => removeFormRow(idx)} aria-label="Remove itinerary">
                      <IconTrash size={16} />
                    </ActionIcon>
                  </Tooltip>
                </Group>
                {fields}
              </Paper>
            );
          })}
          {!editing && (
            <Button
              variant="light"
              color="teal"
              leftSection={<IconPlus size={16} />}
              onClick={addFormRow}
              style={{ borderStyle: "dashed", borderWidth: 1, borderColor: "var(--mantine-color-teal-4)" }}
            >
              Add another itinerary
            </Button>
          )}
          <Divider />
          <Group justify="flex-end">
            <Button variant="subtle" onClick={closeDrawer}>
              Cancel
            </Button>
            <Button onClick={handleSubmit} loading={saving}>
              {editing ? "Save Changes" : forms.length > 1 ? `Add ${forms.length} Itineraries` : "Add Itinerary"}
            </Button>
          </Group>
        </Stack>
      </Drawer>

      {/* Delete modal */}
      <Modal opened={!!deleteTarget} onClose={() => setDeleteTarget(null)} title="Delete Itinerary" centered size="sm">
        <Stack>
          <Text size="sm">
            Delete{" "}
            <Text span fw={700}>
              {deleteTarget ? contentLabel(deleteTarget) : ""}
            </Text>{" "}
            ({deleteTarget ? `${fmt(deleteTarget.available_from)} – ${fmt(deleteTarget.available_to)}` : ""})? Members
            will no longer be able to book it.
          </Text>
          <Group justify="flex-end">
            <Button variant="subtle" onClick={() => setDeleteTarget(null)}>
              Cancel
            </Button>
            <Button color="red" onClick={handleDelete} loading={deleting}>
              Delete
            </Button>
          </Group>
        </Stack>
      </Modal>
      {destinationId && accessScope.create && (
        <ScheduleImportModal
          opened={importOpened}
          onClose={closeImport}
          destinationId={destinationId}
          contentOptions={contentOptions}
          existing={itineraries}
          defaultUnits={DEFAULT_UNITS}
          onImported={load}
        />
      )}

      {/* Bulk delete modal */}
      <Modal opened={bulkDeleteOpen} onClose={() => setBulkDeleteOpen(false)} title="Delete Itineraries" centered size="sm">
        <Stack>
          <Text size="sm">
            Delete{" "}
            <Text span fw={700}>
              {selectedRows.length} itinerar{selectedRows.length === 1 ? "y" : "ies"}
            </Text>
            ? Members will no longer be able to book them.
          </Text>
          <Group justify="flex-end">
            <Button variant="subtle" onClick={() => setBulkDeleteOpen(false)}>
              Cancel
            </Button>
            <Button color="red" onClick={bulkDelete} loading={bulkBusy}>
              Delete {selectedRows.length}
            </Button>
          </Group>
        </Stack>
      </Modal>
    </Container>
  );
}
