import { useMemo, useState } from "react";
import {
  Badge,
  Button,
  Group,
  Modal,
  Paper,
  Select,
  Stack,
  Table,
  Text,
  ThemeIcon,
} from "@mantine/core";
import { CheckCircle2, Layers, Lock, LockOpen, PlayCircle, Repeat, XCircle } from "lucide-react";

import { useMutation, useQuery } from "@tanstack/react-query";

import { BookingStatusBadge } from "@/components/bookings/BookingStatusBadge";
import { api } from "@/services/api";
import { useToast } from "@/hooks/use-toast";
import type { TrainScheduleDetail } from "@/types/trainScheduling";

interface ScheduleBatchPanelProps {
  schedule: TrainScheduleDetail;
}

const windowColor: Record<string, string> = {
  OPEN: "edr-green",
  FULL: "orange",
  CLOSED: "gray",
};

export function ScheduleBatchPanel({ schedule }: ScheduleBatchPanelProps) {
  const { toast } = useToast();
  const actions = {
    runBatch: useMutation(api.trainScheduling.runBatch.mutationOptions()),
    setWindow: useMutation(api.trainScheduling.setBookingWindow.mutationOptions()),
    markPaid: useMutation(api.trainScheduling.markBookingPaid.mutationOptions()),
    expire: useMutation(api.trainScheduling.expireBooking.mutationOptions()),
    moveSchedule: useMutation(
      api.trainScheduling.moveBookingSchedule.mutationOptions(),
    ),
  };
  const windowStatus = (schedule as { bookingWindowStatus?: string }).bookingWindowStatus ?? "OPEN";
  const locked = schedule.status === "DISPATCHED" || schedule.status === "ARRIVED";

  const [moveBookingId, setMoveBookingId] = useState<string | null>(null);
  const [moveTarget, setMoveTarget] = useState<string | null>(null);

  const { data: targets } = useQuery(
    api.trainScheduling.bookableSchedules.queryOptions({
      input: {
        originYardId: schedule.originStation?.id,
        destinationYardId: schedule.destinationStation?.id,
      },
      enabled: Boolean(
        schedule.originStation?.id && schedule.destinationStation?.id,
      ),
    }),
  );
  const moveOptions = useMemo(
    () =>
      (targets ?? [])
        .filter((s) => s.id !== schedule.id)
        .map((s) => ({
          value: s.id,
          label: `${s.routeName ?? `${s.origin} → ${s.destination}`} · ${new Date(
            s.scheduleDate,
          ).toLocaleString()} · ${s.remainingWagons}/${s.maxWagons} free`,
        })),
    [targets, schedule.id],
  );

  const bookings = schedule.bookings ?? [];

  const run = (fn: Promise<unknown>, ok: string) =>
    fn
      .then(() => toast({ title: ok }))
      .catch(() => toast({ title: "Action failed", variant: "destructive" }));

  return (
    <Paper radius="lg" withBorder p="lg" style={{ borderColor: "var(--mantine-color-gray-2)" }}>
      <Group justify="space-between" align="center" mb="md" wrap="wrap">
        <Group gap="sm">
          <ThemeIcon size={36} radius="md" variant="light" color="edr-green">
            <Layers size={18} />
          </ThemeIcon>
          <div>
            <Text fw={700}>Batch allocation</Text>
            <Text size="xs" c="dimmed">
              {bookings.length} allocated · {schedule.trainSet?.wagonCount ?? 0} wagons used
            </Text>
          </div>
        </Group>
        <Group gap="sm">
          <Badge color={windowColor[windowStatus] ?? "gray"} variant="light" radius="sm" size="lg">
            Window: {windowStatus}
          </Badge>
        </Group>
      </Group>

      {!locked && (
        <Group gap="sm" mb="md">
          <Button
            size="compact-sm"
            variant="light"
            color="edr-green"
            leftSection={<PlayCircle size={15} />}
            loading={actions.runBatch.isPending}
            onClick={() => run(actions.runBatch.mutateAsync(schedule.id), "Batch fill run")}
          >
            Run batch fill
          </Button>
          {windowStatus === "CLOSED" ? (
            <Button
              size="compact-sm"
              variant="default"
              leftSection={<LockOpen size={15} />}
              loading={actions.setWindow.isPending}
              onClick={() =>
                run(
                  actions.setWindow.mutateAsync({ id: schedule.id, status: "OPEN" }),
                  "Window opened",
                )
              }
            >
              Open window
            </Button>
          ) : (
            <Button
              size="compact-sm"
              variant="default"
              leftSection={<Lock size={15} />}
              loading={actions.setWindow.isPending}
              onClick={() =>
                run(
                  actions.setWindow.mutateAsync({ id: schedule.id, status: "CLOSED" }),
                  "Window closed",
                )
              }
            >
              Close window
            </Button>
          )}
        </Group>
      )}

      {bookings.length === 0 ? (
        <Text size="sm" c="dimmed">
          No bookings allocated yet. The batch cron fills this schedule by priority; paid bookings are
          assigned automatically.
        </Text>
      ) : (
        <Table verticalSpacing="xs" highlightOnHover>
          <Table.Thead>
            <Table.Tr>
              <Table.Th>Booking</Table.Th>
              <Table.Th>Customer</Table.Th>
              <Table.Th>Status</Table.Th>
              <Table.Th ta="right">Actions</Table.Th>
            </Table.Tr>
          </Table.Thead>
          <Table.Tbody>
            {bookings.map((b) => (
              <Table.Tr key={b.id}>
                <Table.Td>
                  <Text size="sm" fw={600}>
                    {b.reference ?? b.id.slice(0, 8)}
                  </Text>
                </Table.Td>
                <Table.Td>
                  <Text size="sm" c="dimmed">
                    {b.customer ?? "—"}
                  </Text>
                </Table.Td>
                <Table.Td>
                  <BookingStatusBadge status={b.status ?? ""} />
                </Table.Td>
                <Table.Td>
                  {!locked && (
                    <Group gap={6} justify="flex-end" wrap="nowrap">
                      {b.status !== "PAID" && (
                        <Button
                          size="compact-xs"
                          variant="light"
                          color="edr-green"
                          leftSection={<CheckCircle2 size={13} />}
                          onClick={() => run(actions.markPaid.mutateAsync(b.id), "Marked paid")}
                        >
                          Mark paid
                        </Button>
                      )}
                      <Button
                        size="compact-xs"
                        variant="subtle"
                        color="orange"
                        leftSection={<Repeat size={13} />}
                        onClick={() => {
                          setMoveBookingId(b.id);
                          setMoveTarget(null);
                        }}
                      >
                        Move
                      </Button>
                      <Button
                        size="compact-xs"
                        variant="subtle"
                        color="red"
                        leftSection={<XCircle size={13} />}
                        onClick={() => run(actions.expire.mutateAsync(b.id), "Reservation expired")}
                      >
                        Expire
                      </Button>
                    </Group>
                  )}
                </Table.Td>
              </Table.Tr>
            ))}
          </Table.Tbody>
        </Table>
      )}

      <Modal
        opened={Boolean(moveBookingId)}
        onClose={() => setMoveBookingId(null)}
        title="Move booking to another schedule"
        centered
        radius="lg"
      >
        <Stack gap="md">
          <Select
            label="Target schedule (same route)"
            placeholder="Select an OPEN schedule"
            data={moveOptions}
            value={moveTarget}
            onChange={setMoveTarget}
            searchable
            nothingFoundMessage="No other open schedules on this route"
          />
          <Group justify="flex-end">
            <Button variant="default" onClick={() => setMoveBookingId(null)}>
              Cancel
            </Button>
            <Button
              color="edr-green"
              disabled={!moveTarget}
              loading={actions.moveSchedule.isPending}
              onClick={() => {
                if (!moveBookingId || !moveTarget) return;
                run(
                  actions.moveSchedule.mutateAsync({
                    bookingId: moveBookingId,
                    trainScheduleId: moveTarget,
                  }),
                  "Booking moved",
                ).then(() => setMoveBookingId(null));
              }}
            >
              Move booking
            </Button>
          </Group>
        </Stack>
      </Modal>
    </Paper>
  );
}
