import {
  ActionIcon,
  Box,
  Button,
  Card,
  Group,
  Stack,
  Tabs,
  Text,
  TextInput,
} from "@mantine/core";
import {
  AlertTriangle,
  ArrowRight,
  Calendar,
  CheckCircle2,
  Clock,
  LayoutList,
  Package,
  Plus,
  RefreshCw,
  Search,
  User,
  X,
} from "lucide-react";
import { useCallback, useMemo, useRef, useState } from "react";
import { useNavigate } from "react-router-dom";

import { BookingActionsMenu } from "@/components/bookings/BookingActionsMenu";
import { BookingApprovalProgressCell } from "@/components/bookings/BookingApprovalProgressCell";
import { BookingPriorityBadge } from "@/components/bookings/BookingPriorityBadge";
import { BookingStatusBadge } from "@/components/bookings/BookingStatusBadge";
import {
  BookingStatusTabs,
  type BookingStatusTabKey,
} from "@/components/bookings/BookingStatusTabs";
import { BookingTableEmpty } from "@/components/bookings/BookingTableEmpty";
import { OperationsBookingQueue } from "@/components/bookings/OperationsBookingQueue";
import { OperationsScheduledBookings } from "@/components/bookings/OperationsScheduledBookings";
import { bookingTable } from "@/components/bookings/booking-ui.styles";
import { KpiStrip, PageContainer, PageHeader } from "@/components/page";
import { AllocateBookingWizard } from "@/components/trainScheduling/AllocateBookingWizard";
import { BOOKING_LIST_TABS } from "@/features/bookings/booking-status.config";
import { toBookingListRow } from "@/features/bookings/mapBookingListRow";
import {
  useBookingDetail,
  useBookingList,
  useBookingListSummary,
} from "@/hooks/bookings/useBookings";
import type { BookingListFilter } from "@/services/bookings.service";
import type { BookingListRow } from "@/types/booking";
import {
  Badge,
  DataTable,
  DataTableFooter,
  usePagination,
  type ColumnDef,
} from "@edr/ui-common";

function getStatusesForTab(tab: BookingStatusTabKey): string | undefined {
  const match = BOOKING_LIST_TABS.find((t) => t.key === tab);
  if (!match?.statuses?.length) return undefined;
  return match.statuses.join(",");
}

function formatDate(value: string | null | undefined): string {
  if (!value) return "—";
  const d = new Date(value);
  return Number.isNaN(d.getTime())
    ? "—"
    : d.toLocaleDateString(undefined, {
        year: "numeric",
        month: "short",
        day: "numeric",
      });
}

type OperationsSubTab = "ready" | "scheduled";

export default function BookingRequestsPage() {
  const navigate = useNavigate();
  const { pagination, setPagination } = usePagination({ pageSize: 10 });
  const [query, setQuery] = useState("");
  const [activeTab, setActiveTab] = useState<BookingStatusTabKey>("all");
  const [operationsSubTab, setOperationsSubTab] = useState<OperationsSubTab>("ready");
  const [allocateOpen, setAllocateOpen] = useState(false);
  const [allocateIds, setAllocateIds] = useState<string[]>([]);
  const suppressRowClickRef = useRef(false);
  const suppressRowClick = useCallback(() => {
    suppressRowClickRef.current = true;
    window.setTimeout(() => {
      suppressRowClickRef.current = false;
    }, 400);
  }, []);

  const tabStatuses = getStatusesForTab(activeTab);
  const isOperationsTab = activeTab === "operations";

  const filter: BookingListFilter = useMemo(() => {
    if (isOperationsTab) {
      if (operationsSubTab === "ready") {
        return {
          page: 1,
          pageSize: 100,
          statuses: "PAID",
          schedulingStatuses: "NOT_SCHEDULED,HOLDING,ELIGIBLE",
          assignedToSchedule: "false",
          sortBy: "isGovernment",
          sortOrder: "DESC",
          tab: activeTab,
        };
      }
      return {
        page: 1,
        pageSize: 100,
        statuses: "PAID",
        schedulingStatuses: "SCHEDULED,DISPATCHED",
        sortBy: "scheduledDate",
        sortOrder: "ASC",
        tab: activeTab,
      };
    }
    return {
      page: pagination.pageIndex + 1,
      pageSize: pagination.pageSize,
      sortBy: "createdAt",
      sortOrder: "DESC",
      tab: activeTab,
      ...(tabStatuses ? { statuses: tabStatuses } : {}),
    };
  }, [
    isOperationsTab,
    operationsSubTab,
    pagination.pageIndex,
    pagination.pageSize,
    activeTab,
    tabStatuses,
  ]);

  const { data, isLoading, isError, refetch, isFetching } = useBookingList(filter);
  const primaryAllocateId = allocateIds[0];
  const { data: allocateBooking } = useBookingDetail(
    allocateOpen ? primaryAllocateId : undefined,
  );
  const {
    data: summary,
    isLoading: summaryLoading,
    refetch: refetchSummary,
  } = useBookingListSummary(filter);

  const rows = useMemo(() => {
    const items = (data?.items ?? []).map(toBookingListRow);
    const q = query.trim().toLowerCase();
    if (!q) return items;
    return items.filter(
      (b) =>
        b.reference.toLowerCase().includes(q) ||
        b.customerLabel.toLowerCase().includes(q),
    );
  }, [data?.items, query]);

  const total = data?.total ?? 0;
  const pageCount = Math.max(1, Math.ceil(total / pagination.pageSize));
  const hasSearch = query.trim().length > 0;
  const showEmpty = !isLoading && !isError && rows.length === 0;

  const metrics = summary?.metrics;
  const tabCounts = summary?.tabs;

  const handleRefresh = useCallback(() => {
    void refetch();
    void refetchSummary();
  }, [refetch, refetchSummary]);

  const handleAllocateFromQueue = useCallback(
    (ids: string[]) => {
      const selected = rows.filter((b) => ids.includes(b.id));
      const sorted = [...selected].sort(
        (a, b) => (b.priorityScore ?? 0) - (a.priorityScore ?? 0),
      );
      setAllocateIds(sorted.map((b) => b.id));
      setAllocateOpen(true);
    },
    [rows],
  );

  const handleRowClick = useCallback(
    (row: BookingListRow) => {
      if (suppressRowClickRef.current) return;
      navigate(`/dashboard/booking-requests/${row.id}`);
    },
    [navigate],
  );

  const columns: ColumnDef<BookingListRow>[] = [
    {
      id: "booking",
      header: () => <span className={bookingTable.headerCell}>Booking</span>,
      cell: ({ row }) => {
        const b = row.original;
        return (
          <div className="flex items-center gap-3 py-1.5">
            <div className={bookingTable.rowIcon}>
              <Package className="size-4" strokeWidth={1.75} />
            </div>
            <div className="min-w-0">
              <p className="truncate font-medium text-foreground">{b.reference}</p>
              <p className="mt-0.5 flex items-center gap-1 truncate text-xs text-muted-foreground">
                <User className="size-3 shrink-0 opacity-70" />
                {b.customerLabel}
              </p>
            </div>
          </div>
        );
      },
    },
    {
      id: "route",
      header: () => <span className={bookingTable.headerCell}>Route</span>,
      cell: ({ row }) => {
        const b = row.original;
        return (
          <div className="space-y-1 py-1">
            <div className="flex items-center gap-1.5 text-sm font-medium text-foreground">
              <span className="max-w-[8rem] truncate">{b.originLabel}</span>
              <ArrowRight className="size-3.5 shrink-0 text-muted-foreground" />
              <span className="max-w-[8rem] truncate">{b.destinationLabel}</span>
            </div>
            <div className="flex gap-1.5">
              <Badge
                variant="outline"
                className="h-5 border-border/50 bg-background/50 px-1.5 text-[10px] font-medium uppercase backdrop-blur-sm"
              >
                {b.tradeDirection}
              </Badge>
              <Badge
                variant="secondary"
                className="h-5 bg-muted/40 px-1.5 text-[10px] font-medium"
              >
                {b.freightType}
              </Badge>
            </div>
          </div>
        );
      },
    },
    {
      id: "status",
      size: 200,
      minSize: 180,
      header: () => <span className={bookingTable.headerCell}>Status</span>,
      cell: ({ row }) => (
        <div className="py-1">
          <BookingStatusBadge
            status={row.original.status}
            consolidated={Boolean(row.original.consolidationPartnerId)}
            partnerReference={row.original.consolidationPartnerReference}
          />
        </div>
      ),
      meta: {
        headerClassName: "min-w-[11rem]",
        cellClassName: "min-w-[11rem]",
      },
    },
    {
      id: "approval",
      header: () => (
        <span className={bookingTable.headerCell}>Approval</span>
      ),
      cell: ({ row }) => <BookingApprovalProgressCell row={row.original} />,
    },
    {
      id: "scheduled",
      header: () => <span className={bookingTable.headerCell}>Scheduled</span>,
      cell: ({ row }) => (
        <span className="inline-flex items-center gap-1.5 text-sm text-muted-foreground">
          <Calendar className="size-3.5" />
          {formatDate(row.original.scheduledDate)}
        </span>
      ),
    },
    {
      id: "priority",
      header: () => <span className={bookingTable.headerCell}>Priority</span>,
      cell: ({ row }) => (
        <BookingPriorityBadge score={row.original.priorityScore} />
      ),
    },
    {
      id: "actions",
      size: 140,
      cell: ({ row }) => (
        <BookingActionsMenu
          row={row.original}
          variant="table"
          onSuppressRowClick={suppressRowClick}
        />
      ),
    },
  ];

  return (
    <PageContainer>
      <Stack gap="lg">
          <PageHeader
            title="Booking requests"
            subtitle="Review, approve, and schedule freight booking requests."
            action={
              <>
                <Button
                  color="edr-green"
                  leftSection={<Plus size={18} />}
                  onClick={() => navigate("/dashboard/booking-requests/new")}
                >
                  Create booking
                </Button>
                <Button
                  variant="default"
                  leftSection={<RefreshCw size={16} />}
                  loading={isFetching}
                  onClick={handleRefresh}
                >
                  Refresh
                </Button>
              </>
            }
          />

          <KpiStrip
            loading={summaryLoading}
            items={[
              {
                label: "In queue",
                value: metrics?.inQueue ?? 0,
                icon: LayoutList,
                color: "edr-green",
              },
              {
                label: "Needs action",
                value: metrics?.needsAction ?? 0,
                icon: Clock,
                color: "yellow",
              },
              {
                label: "Urgent",
                value: metrics?.urgent ?? 0,
                icon: AlertTriangle,
                color: "red",
              },
              {
                label: "Completed",
                value: tabCounts?.completed ?? 0,
                icon: CheckCircle2,
                color: "edr-green",
              },
            ]}
          />

          <BookingStatusTabs
            active={activeTab}
            onChange={(tab) => {
              setActiveTab(tab);
              setPagination({ pageIndex: 0, pageSize: pagination.pageSize });
            }}
            counts={tabCounts}
          />

          <Card p={0}>
            <Stack gap={0}>
              <Box px="md" pt="md" pb="sm" w="100%">
                <Group justify="space-between" gap="md" wrap="wrap">
                  <TextInput
                    placeholder="Search reference or customer…"
                    leftSection={<Search size={18} />}
                    value={query}
                    onChange={(e) => setQuery(e.target.value)}
                    rightSection={
                      query && (
                        <ActionIcon
                          size="sm"
                          color="gray"
                          radius="md"
                          variant="transparent"
                          onClick={() => setQuery("")}
                        >
                          <X size={16} />
                        </ActionIcon>
                      )
                    }
                    style={{ flex: 1, minWidth: "200px" }}
                    radius="lg"
                  />
                  <Text size="sm" c="dimmed">
                    {total} record{total !== 1 ? "s" : ""}
                  </Text>
                </Group>
              </Box>

              {isOperationsTab ? (
                <Box px="md" pb="md">
                  <Stack gap="md">
                    <Tabs
                      value={operationsSubTab}
                      onChange={(value) =>
                        setOperationsSubTab((value as OperationsSubTab) ?? "ready")
                      }
                    >
                      <Tabs.List>
                        <Tabs.Tab value="ready">Ready to allocate</Tabs.Tab>
                        <Tabs.Tab value="scheduled">On train / scheduled</Tabs.Tab>
                      </Tabs.List>
                    </Tabs>
                    {isError ? (
                      <BookingTableEmpty
                        isError
                        hasSearch={false}
                        onRetry={handleRefresh}
                      />
                    ) : operationsSubTab === "ready" ? (
                      <OperationsBookingQueue
                        bookings={rows}
                        isLoading={isLoading}
                        onAllocate={handleAllocateFromQueue}
                      />
                    ) : (
                      <OperationsScheduledBookings
                        bookings={rows}
                        isLoading={isLoading}
                      />
                    )}
                  </Stack>
                </Box>
              ) : showEmpty ? (
                <Box px="md" pb="md">
                  <BookingTableEmpty
                    isError={isError}
                    hasSearch={hasSearch}
                    onRetry={handleRefresh}
                  />
                </Box>
              ) : (
                <Box style={{ overflowX: "auto" }} w="100%">
                  <DataTable
                    columns={columns}
                    data={rows}
                    status={isLoading ? "loading" : isError ? "error" : "success"}
                    onRowClick={handleRowClick}
                    pagination={{
                      pageIndex: pagination.pageIndex,
                      pageSize: pagination.pageSize,
                      pageCount,
                      totalCount: total,
                    }}
                    tableOptions={{
                      state: { pagination },
                      onPaginationChange: setPagination,
                      manualPagination: true,
                      pageCount,
                    }}
                    containerClassName="border-0 shadow-none bg-transparent"
                    footer={DataTableFooter}
                  />
                </Box>
              )}
            </Stack>
          </Card>
        </Stack>

        {allocateBooking ? (
          <AllocateBookingWizard
            booking={allocateBooking}
            opened={allocateOpen}
            onClose={() => {
              setAllocateOpen(false);
              setAllocateIds([]);
              void refetch();
            }}
            initialBookingIds={allocateIds}
          />
        ) : null}
    </PageContainer>
  );
}
