import type { ColumnDef } from "@edr/ui-common";
import {
  ActionIcon,
  Box,
  Button,
  Card,
  Group,
  Menu,
  Modal,
  Select,
  SimpleGrid,
  Stack,
  Text,
  TextInput,
  ThemeIcon,
} from "@mantine/core";
import { isAxiosError } from "axios";
import {
  ArrowRight,
  Ban,
  CalendarClock,
  Eye,
  MoreHorizontal,
  Navigation,
  Send,
  Train,
  Weight,
} from "lucide-react";
import { useEffect, useMemo, useState } from "react";
import { useNavigate } from "react-router-dom";

import FleetToolbar from "@/components/fleet/FleetToolbar";
import { useFleetViewMode } from "@/components/fleet/useFleetViewMode";
import { KpiStrip, PageContainer, PageHeader } from "@/components/page";
import RuleEngineListFooter from "@/components/ruleEngine/RuleEngineListFooter";
import { ruleEngineTable } from "@/components/ruleEngine/ruleEngineStyles";
import { FreightTypeBadge } from "@/components/trainScheduling/ScheduleStatusBadge";
import {
  RouteCorridor,
  StatusPill,
} from "@/components/trainScheduling/scheduleVisuals";
import { useMutation, useQuery } from "@tanstack/react-query";
import { api } from "@/services/api";
import { useToast } from "@/hooks/use-toast";
import type { TrainScheduleListItem } from "@/types/trainScheduling";
import { DataTable, DataTableFooter, usePagination } from "@edr/ui-common";

const splitDate = (value?: string | null) => {
  if (!value) return { day: "—", time: "" };
  const date = new Date(value);
  if (Number.isNaN(date.getTime())) return { day: "—", time: "" };
  return {
    day: new Intl.DateTimeFormat("en", {
      month: "short",
      day: "2-digit",
      year: "numeric",
    }).format(date),
    time: new Intl.DateTimeFormat("en", {
      hour: "2-digit",
      minute: "2-digit",
    }).format(date),
  };
};

const parseError = (error: unknown, fallback: 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;
};

export default function TrainScheduleV2ListPage() {
  const navigate = useNavigate();
  const { toast } = useToast();
  const { viewMode, setViewMode } = useFleetViewMode("train-scheduling-v2");
  const { pagination, setPagination } = usePagination({ pageSize: 10 });
  const [search, setSearch] = useState("");
  const [statusFilter, setStatusFilter] = useState("ALL");
  const [freightFilter, setFreightFilter] = useState("ALL");
  const [createOpen, setCreateOpen] = useState(false);
  const [routeId, setRouteId] = useState("");
  const [scheduleDate, setScheduleDate] = useState("");
  const [locomotiveId, setLocomotiveId] = useState("");

  const schedulesQuery = useQuery(
    api.trainScheduling.scheduleList.queryOptions({ input: {} }),
  );
  const routesQuery = useQuery(api.routes.list.queryOptions());
  const locomotivesQuery = useQuery(
    api.trainScheduling.availableLocomotives.queryOptions({
      input: { routeId: routeId || undefined },
    }),
  );
  const create = useMutation(api.trainScheduling.createSchedule.mutationOptions());
  const cancel = useMutation(api.trainScheduling.cancelSchedule.mutationOptions());

  const activeRoutes = useMemo(
    () => (routesQuery.data ?? []).filter((r) => r.isActive),
    [routesQuery.data],
  );

  const selectedRoute = activeRoutes.find((r) => r.id === routeId);

  const locomotiveYardHint = useMemo(() => {
    if (!selectedRoute) return "Select a route first";
    const originLabel =
      selectedRoute.originYard?.label ??
      selectedRoute.originYard?.code ??
      "the route origin yard";
    return `Only locomotives currently at ${originLabel} are shown`;
  }, [selectedRoute]);

  useEffect(() => {
    setLocomotiveId("");
  }, [routeId]);

  const allSchedules = schedulesQuery.data ?? [];

  const stats = useMemo(() => {
    const base = {
      total: allSchedules.length,
      scheduled: 0,
      dispatched: 0,
      draft: 0,
      weight: 0,
    };
    for (const s of allSchedules) {
      if (s.status === "SCHEDULED") base.scheduled += 1;
      if (s.status === "DISPATCHED") base.dispatched += 1;
      if (s.status === "DRAFT") base.draft += 1;
      base.weight += s.totalWeightTons ?? 0;
    }
    return base;
  }, [allSchedules]);

  const filtered = useMemo(() => {
    const query = search.trim().toLowerCase();
    return allSchedules.filter((s) => {
      if (statusFilter !== "ALL" && s.status !== statusFilter) return false;
      if (freightFilter !== "ALL" && s.freightType !== freightFilter) return false;
      if (!query) return true;
      const haystack = [
        s.trainNumber,
        s.routeName,
        s.origin,
        s.destination,
        s.locomotive?.code,
        s.freightType,
        s.status,
      ]
        .filter(Boolean)
        .join(" ")
        .toLowerCase();
      return haystack.includes(query);
    });
  }, [allSchedules, search, statusFilter, freightFilter]);

  const pageCount = Math.max(1, Math.ceil(filtered.length / pagination.pageSize));
  const paged = useMemo(() => {
    const start = pagination.pageIndex * pagination.pageSize;
    return filtered.slice(start, start + pagination.pageSize);
  }, [filtered, pagination]);

  const columns = useMemo((): ColumnDef<TrainScheduleListItem>[] => {
    const headerClassName = ruleEngineTable.headerCell;
    const cellClassName = ruleEngineTable.bodyCell;
    return [
      {
        id: "date",
        header: "Departure",
        meta: { headerClassName, cellClassName },
        cell: ({ row }) => {
          const { day, time } = splitDate(row.original.scheduleDate);
          return (
            <Group gap="sm" wrap="nowrap">
              <Box
                style={{
                  display: "flex",
                  alignItems: "center",
                  justifyContent: "center",
                  width: 34,
                  height: 34,
                  borderRadius: 9,
                  background: "var(--mantine-color-edr-green-0)",
                  color: "var(--mantine-color-edr-green-7)",
                  flexShrink: 0,
                }}
              >
                <CalendarClock size={16} />
              </Box>
              <Stack gap={0}>
                <Text size="sm" fw={600} lh={1.2}>
                  {day}
                </Text>
                <Text size="xs" c="dimmed" lh={1.2}>
                  {time || "—"}
                </Text>
              </Stack>
            </Group>
          );
        },
      },
      {
        id: "route",
        header: "Route",
        meta: { headerClassName, cellClassName },
        cell: ({ row }) => (
          <Stack gap={4}>
            <Text size="sm" fw={600} lh={1.2}>
              {row.original.routeName ?? "—"}
            </Text>
            <Box maw={220}>
              <RouteCorridor
                origin={row.original.origin}
                destination={row.original.destination}
                variant="compact"
              />
            </Box>
          </Stack>
        ),
      },
      {
        id: "freight",
        header: "Freight",
        meta: { headerClassName, cellClassName },
        cell: ({ row }) => <FreightTypeBadge freightType={row.original.freightType} />,
      },
      {
        id: "loco",
        header: "Locomotive",
        meta: { headerClassName, cellClassName },
        cell: ({ row }) =>
          row.original.locomotive?.code ? (
            <Group gap={6} wrap="nowrap">
              <Train size={14} color="var(--mantine-color-gray-5)" />
              <Text size="sm" fw={500}>
                {row.original.locomotive.code}
              </Text>
            </Group>
          ) : (
            <Text size="sm" c="dimmed">
              —
            </Text>
          ),
      },
      {
        id: "metrics",
        header: "Load",
        meta: { headerClassName, cellClassName },
        cell: ({ row }) => (
          <Group gap={6} wrap="nowrap">
            <MetricChip value={row.original.bookingsCount} label="bkg" />
            <MetricChip value={row.original.wagonCount} label="wgn" />
            <MetricChip value={`${row.original.totalWeightTons}T`} label="" subtle />
          </Group>
        ),
      },
      {
        id: "status",
        header: "Status",
        meta: { headerClassName, cellClassName },
        cell: ({ row }) => <StatusPill status={row.original.status} />,
      },
      {
        id: "actions",
        size:32,
        meta: { headerClassName, cellClassName: `${cellClassName} whitespace-nowrap` },
        cell: ({ row }) => {
          const schedule = row.original;
          return (
            <Group justify="flex-end" onClick={(e) => e.stopPropagation()}>
              <Menu position="bottom-end" withinPortal shadow="md" width={190}>
                <Menu.Target>
                  <ActionIcon variant="subtle" color="gray" aria-label="Row actions">
                    <MoreHorizontal size={16} />
                  </ActionIcon>
                </Menu.Target>
                <Menu.Dropdown>
                  <Menu.Item
                    leftSection={<Eye size={15} />}
                    onClick={() =>
                      navigate(`/dashboard/operations/train-scheduling-v2/${schedule.id}`)
                    }
                  >
                    View detail
                  </Menu.Item>
                  {["DISPATCHED", "ARRIVED"].includes(schedule.status) ? (
                    <Menu.Item
                      leftSection={<Navigation size={15} />}
                      onClick={() =>
                        navigate(
                          `/dashboard/operations/train-scheduling-v2/${schedule.id}/track`,
                        )
                      }
                    >
                      Track
                    </Menu.Item>
                  ) : null}
                  {["DRAFT", "SCHEDULED"].includes(schedule.status) ? (
                    <Menu.Item
                      color="red"
                      leftSection={<Ban size={15} />}
                      onClick={async () => {
                        try {
                          await cancel.mutateAsync({
                            id: schedule.id,
                            freightType: schedule.freightType ?? "CONTAINER",
                          });
                          toast({ title: "Schedule cancelled" });
                        } catch (err) {
                          toast({
                            title: "Cancel failed",
                            description: parseError(err, "Could not cancel"),
                            variant: "destructive",
                          });
                        }
                      }}
                    >
                      Cancel schedule
                    </Menu.Item>
                  ) : null}
                </Menu.Dropdown>
              </Menu>
            </Group>
          );
        },
      },
    ];
  }, [navigate, cancel.isPending, cancel, toast]);

  const handleCreate = async () => {
    if (!routeId || !scheduleDate || !locomotiveId) {
      toast({ title: "Select route, date, and locomotive", variant: "destructive" });
      return;
    }
    try {
      const created = await create.mutateAsync({
        payload: { routeId, scheduleDate, locomotiveId },
      });
      toast({ title: "Train schedule created" });
      setCreateOpen(false);
      navigate(`/dashboard/operations/train-scheduling-v2/${created.id}`);
    } catch (err) {
      toast({
        title: "Create failed",
        description: parseError(err, "Could not create schedule"),
        variant: "destructive",
      });
    }
  };

  const tableStatus = schedulesQuery.isLoading
    ? "loading"
    : schedulesQuery.isError
      ? "error"
      : "success";

  return (
    <PageContainer>
      <PageHeader
        title="Train Schedules"
        subtitle="Operational train scheduling with full allocation workflow."
        action={
          <Button leftSection={<Train size={18} />} onClick={() => setCreateOpen(true)}>
            New schedule
          </Button>
        }
      />

      <KpiStrip
        items={[
          { label: "Total trains", value: stats.total, icon: Train },
          { label: "Scheduled", value: stats.scheduled, icon: CalendarClock },
          { label: "Dispatched", value: stats.dispatched, icon: Send },
          { label: "Planned load", value: `${Math.round(stats.weight)}T`, icon: Weight },
        ]}
      />

      <Card p={0}>
        <Stack gap={0}>
          <Box px="md" pt="md" pb="sm" w="100%">
            <FleetToolbar
              search={search}
              onSearchChange={setSearch}
              searchPlaceholder="Search schedules…"
              viewMode={viewMode}
              onViewModeChange={setViewMode}
              filters={
                <>
                  <Select
                    size="sm"
                    radius="lg"
                    value={statusFilter}
                    onChange={(v) => v && setStatusFilter(v)}
                    data={[
                      { value: "ALL", label: "All statuses" },
                      { value: "DRAFT", label: "Draft" },
                      { value: "SCHEDULED", label: "Scheduled" },
                      { value: "DISPATCHED", label: "Dispatched" },
                      { value: "CANCELLED", label: "Cancelled" },
                    ]}
                    w={150}
                    styles={{ input: { borderColor: "var(--mantine-color-gray-3)" } }}
                  />
                  <Select
                    size="sm"
                    radius="lg"
                    value={freightFilter}
                    onChange={(v) => v && setFreightFilter(v)}
                    data={[
                      { value: "ALL", label: "All freight" },
                      { value: "CONTAINER", label: "Container" },
                      { value: "BULK", label: "Bulk" },
                      { value: "MIXED", label: "Mixed" },
                    ]}
                    w={140}
                    styles={{ input: { borderColor: "var(--mantine-color-gray-3)" } }}
                  />
                </>
              }
            />
          </Box>

          {viewMode === "table" ? (
            <DataTable
              columns={columns}
              data={paged}
              status={tableStatus}
              onRowClick={(schedule) =>
                navigate(`/dashboard/operations/train-scheduling-v2/${schedule.id}`)
              }
              error={
                schedulesQuery.isError
                  ? {
                      message: "Failed to load train schedules.",
                      onRetry: () => void schedulesQuery.refetch(),
                    }
                  : undefined
              }
              emptyMessage="No train schedules found"
              pagination={{
                pageIndex: pagination.pageIndex,
                pageSize: pagination.pageSize,
                pageCount,
                totalCount: filtered.length,
              }}
              tableOptions={{
                manualPagination: true,
                pageCount,
                state: { pagination },
                onPaginationChange: setPagination,
              }}
              containerClassName="border-0 shadow-none bg-transparent"
              footer={({ table, pagination: footerPagination }) => (
                <DataTableFooter
                  table={table}
                  pagination={footerPagination}
                  options={{ labels: { items: "schedules" } }}
                />
              )}
            />
          ) : (
            <Stack gap={0}>
              {!paged.length ? (
                <Text py="xl" ta="center" c="dimmed" size="sm">
                  No train schedules found
                </Text>
              ) : (
                <SimpleGrid cols={{ base: 1, sm: 2, lg: 3 }} spacing="md" p="md">
                  {paged.map((schedule) => (
                    <ScheduleCard
                      key={schedule.id}
                      schedule={schedule}
                      onOpen={() =>
                        navigate(
                          `/dashboard/operations/train-scheduling-v2/${schedule.id}`,
                        )
                      }
                      onTrack={() =>
                        navigate(
                          `/dashboard/operations/train-scheduling-v2/${schedule.id}/track`,
                        )
                      }
                    />
                  ))}
                </SimpleGrid>
              )}
              <RuleEngineListFooter
                pagination={pagination}
                pageCount={pageCount}
                totalCount={filtered.length}
                itemLabel="schedules"
                onPaginationChange={setPagination}
              />
            </Stack>
          )}
        </Stack>
      </Card>

      <Modal
        opened={createOpen}
        onClose={() => setCreateOpen(false)}
        title={<Text fw={600}>Create train schedule</Text>}
        radius="lg"
        centered
      >
        <Stack gap="md">
          <Text size="sm" c="dimmed">
            Schedules support both container and bulk bookings once assigned.
          </Text>
          <Select
            label="Route"
            placeholder="Select route"
            data={activeRoutes.map((r) => ({ value: r.id, label: r.name }))}
            value={routeId || null}
            onChange={(v) => setRouteId(v ?? "")}
            searchable
          />
          {routeId ? (
            <Text size="xs" c="dimmed">
              {locomotiveYardHint}
            </Text>
          ) : null}
          <TextInput
            label="Departure date"
            type="datetime-local"
            value={scheduleDate ? scheduleDate.slice(0, 16) : ""}
            onChange={(e) => {
              const raw = e.currentTarget.value;
              setScheduleDate(raw ? new Date(raw).toISOString() : "");
            }}
          />
          <Select
            label="Locomotive"
            placeholder={routeId ? "Select locomotive" : "Select a route first"}
            data={(locomotivesQuery.data ?? []).map((l) => ({
              value: l.id,
              label: `${l.code}${l.name ? ` — ${l.name}` : ""}`,
            }))}
            value={locomotiveId || null}
            onChange={(v) => setLocomotiveId(v ?? "")}
            searchable
            disabled={!routeId}
            nothingFoundMessage={
              routeId ? "No available locomotives for this corridor" : "Select a route first"
            }
          />
          <Group justify="flex-end">
            <Button variant="default" onClick={() => setCreateOpen(false)}>
              Cancel
            </Button>
            <Button loading={create.isPending} onClick={handleCreate}>
              Create
            </Button>
          </Group>
        </Stack>
      </Modal>
    </PageContainer>
  );
}

function MetricChip({
  value,
  label,
  subtle = false,
}: {
  value: string | number;
  label: string;
  subtle?: boolean;
}) {
  return (
    <Group
      gap={4}
      wrap="nowrap"
      style={{
        padding: "2px 8px",
        borderRadius: 8,
        background: subtle
          ? "var(--mantine-color-gray-1)"
          : "var(--mantine-color-edr-green-0)",
        border: `1px solid ${
          subtle ? "var(--mantine-color-gray-2)" : "var(--mantine-color-edr-green-1)"
        }`,
      }}
    >
      <Text size="sm" fw={700} c={subtle ? "gray.7" : "edr-green.8"} lh={1.2}>
        {value}
      </Text>
      {label ? (
        <Text size="xs" c="dimmed" lh={1.2}>
          {label}
        </Text>
      ) : null}
    </Group>
  );
}

function ScheduleCard({
  schedule,
  onOpen,
  onTrack,
}: {
  schedule: TrainScheduleListItem;
  onOpen: () => void;
  onTrack: () => void;
}) {
  const { day, time } = splitDate(schedule.scheduleDate);
  const canTrack = ["DISPATCHED", "ARRIVED"].includes(schedule.status);
  return (
    <Card
      padding={0}
      withBorder
      onClick={onOpen}
      className="cursor-pointer overflow-hidden transition-[transform,border-color] duration-150 hover:-translate-y-0.5 hover:border-edr-primary!"
    >
      <Stack gap="sm" p="md">
        <Group justify="space-between" align="flex-start" wrap="nowrap">
          <Group gap="sm" wrap="nowrap" style={{ minWidth: 0 }}>
            <ThemeIcon size={38} radius="md" variant="light" color="edr-green">
              <Train size={18} />
            </ThemeIcon>
            <Stack gap={0} style={{ minWidth: 0 }}>
              <Text fw={600} size="sm" lineClamp={1}>
                {schedule.routeName ?? "Train schedule"}
              </Text>
              <Text size="xs" c="dimmed">
                {day} · {time}
              </Text>
            </Stack>
          </Group>
          <StatusPill status={schedule.status} />
        </Group>

        <Box
          p="xs"
          style={{
            borderRadius: 10,
            background: "var(--mantine-color-gray-0)",
            border: "1px solid var(--mantine-color-gray-1)",
          }}
        >
          <RouteCorridor origin={schedule.origin} destination={schedule.destination} />
        </Box>

        <Group justify="space-between" align="center">
          <FreightTypeBadge freightType={schedule.freightType} />
          <Group gap={6} wrap="nowrap">
            <MetricChip value={schedule.bookingsCount} label="bkg" />
            <MetricChip value={schedule.wagonCount} label="wgn" />
            <MetricChip value={`${schedule.totalWeightTons}T`} label="" subtle />
          </Group>
        </Group>

        <Group gap="xs" wrap="nowrap">
          <Button
            variant="light"
            color="edr-green"
            size="sm"
            radius="md"
            style={{ flex: 1 }}
            rightSection={<ArrowRight size={15} />}
            onClick={(e) => {
              e.stopPropagation();
              onOpen();
            }}
          >
            Open schedule
          </Button>
          {canTrack ? (
            <Button
              variant="light"
              color="teal"
              size="sm"
              radius="md"
              leftSection={<Navigation size={15} />}
              onClick={(e) => {
                e.stopPropagation();
                onTrack();
              }}
            >
              Track
            </Button>
          ) : null}
        </Group>
      </Stack>
    </Card>
  );
}
