import {
  ActionIcon,
  Box,
  Button,
  Card,
  Group,
  MultiSelect,
  Select,
  Stack,
  Text,
  TextInput,
} from "@mantine/core";
import { DateInput } from "@mantine/dates";
import { useDebouncedValue } from "@mantine/hooks";
import {
  AlertTriangle,
  ArrowRight,
  Calendar,
  CheckCircle2,
  Clock,
  FilterX,
  LayoutList,
  Package,
  Plus,
  RefreshCw,
  Search,
  User,
  X,
} from "lucide-react";
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { useNavigate, useSearchParams } from "react-router-dom";
import { useQuery } from "@tanstack/react-query";

import { BookingActionsMenu } from "@/components/bookings/BookingActionsMenu";
import { BookingPriorityBadge } from "@/components/bookings/BookingPriorityBadge";
import { BookingStatusBadge } from "@/components/bookings/BookingStatusBadge";
// BookingStatusTabs / Operations* queues removed — replaced by booking-kind tabs.
import { BookingTableEmpty } from "@/components/bookings/BookingTableEmpty";
import { bookingTable } from "@/components/bookings/booking-ui.styles";
import { KpiStrip, PageContainer, PageHeader } from "@/components/page";
import { AllocateBookingWizard } from "@/components/trainScheduling/AllocateBookingWizard";
import { BOOKING_STATUS_STYLES } from "@/features/bookings/booking-status.config";
import { toBookingListRow } from "@/features/bookings/mapBookingListRow";
import {
  useBookingDetail,
  useBookingList,
  useBookingListSummary,
} from "@/hooks/bookings/useBookings";
import { ContractReferenceLink } from "@/components/bookings/ContractReferenceLink";
import { api } from "@/services/api";
import type { BookingListFilter } from "@/services/bookings.service";
import type { BookingListRow } from "@/types/booking";
import {
  Badge,
  DataTable,
  DataTableFooter,
  usePagination,
  type ColumnDef,
} from "@edr/ui-common";

/** Booking kind: one-time vs general-contract bookings. Now a filter, not a tab. */
type BookingKind = "ONE_TIME" | "GENERAL_CONTRACT";

const BOOKING_KIND_OPTIONS: { value: BookingKind; label: string }[] = [
  { value: "ONE_TIME", label: "One-time booking" },
  { value: "GENERAL_CONTRACT", label: "General booking" },
];

/** Status options for the filter select — built from the shared status styles. */
const STATUS_OPTIONS = Object.entries(BOOKING_STATUS_STYLES).map(
  ([value, { label }]) => ({ value, label }),
);

const TRADE_DIRECTION_OPTIONS = [
  { value: "IMPORT", label: "Import" },
  { value: "EXPORT", label: "Export" },
  { value: "DOMESTIC", label: "Domestic" },
];

const FREIGHT_TYPE_OPTIONS = [
  { value: "CONTAINER", label: "Container" },
  { value: "BULK", label: "Bulk" },
];

const PAYMENT_STATUS_OPTIONS = [
  { value: "PENDING", label: "Payment pending" },
  { value: "PNR_GENERATED", label: "PNR generated" },
  { value: "VERIFICATION_IN_PROGRESS", label: "Verification in progress" },
  { value: "PAID", label: "Paid" },
  { value: "FAILED", label: "Payment failed" },
];

const OWNERSHIP_OPTIONS = [
  { value: "true", label: "Government" },
  { value: "false", label: "Private" },
];

/** Local start-of-day → ISO, for inclusive "from" date filters. */
function startOfDayIso(d: Date): string {
  const x = new Date(d);
  x.setHours(0, 0, 0, 0);
  return x.toISOString();
}

/** Local end-of-day → ISO, for inclusive "to" date filters. */
function endOfDayIso(d: Date): string {
  const x = new Date(d);
  x.setHours(23, 59, 59, 999);
  return x.toISOString();
}

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",
      });
}

export default function BookingRequestsPage() {
  const navigate = useNavigate();
  // Deep links land here pre-filtered (?statuses=A,B&tradeDirection=IMPORT) —
  // the header's document-review alarm opens exactly the undecided requests it
  // is counting down for. Read once as the initial state so staff can then
  // change the filters like any other visit.
  const [searchParams] = useSearchParams();
  const { pagination, setPagination } = usePagination({ pageSize: 10 });
  const [query, setQuery] = useState("");
  const [debouncedQuery] = useDebouncedValue(query, 300);
  // Booking kind is a filter now — one list holds both kinds (null = "all").
  const [kindFilter, setKindFilter] = useState<BookingKind | null>(null);
  // Filter controls (empty/null = "all").
  const paramStatuses = searchParams.get("statuses") ?? "";
  const paramDirection = searchParams.get("tradeDirection");
  const [statusFilter, setStatusFilter] = useState<string[]>(() =>
    paramStatuses.split(",").filter(Boolean),
  );
  const [directionFilter, setDirectionFilter] = useState<string | null>(
    paramDirection,
  );
  const [freightTypeFilter, setFreightTypeFilter] = useState<string | null>(null);
  const [paymentStatusFilter, setPaymentStatusFilter] = useState<string | null>(null);
  const [ownershipFilter, setOwnershipFilter] = useState<string | null>(null);
  const [originYardFilter, setOriginYardFilter] = useState<string | null>(null);
  const [destinationYardFilter, setDestinationYardFilter] = useState<string | null>(null);
  const [createdFrom, setCreatedFrom] = useState<Date | null>(null);
  const [createdTo, setCreatedTo] = useState<Date | null>(null);
  const [scheduledFrom, setScheduledFrom] = useState<Date | null>(null);
  const [scheduledTo, setScheduledTo] = useState<Date | null>(null);
  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);
  }, []);

  // Follow the URL when a deep link arrives while the page is already open
  // (clicking the header alarm from this very list). Same-value writes are
  // dropped so a manual filter change is never undone.
  useEffect(() => {
    const next = paramStatuses.split(",").filter(Boolean);
    setStatusFilter((prev) => (prev.join(",") === next.join(",") ? prev : next));
    setDirectionFilter(paramDirection);
  }, [paramStatuses, paramDirection]);

  const filter: BookingListFilter = useMemo(() => {
    return {
      page: pagination.pageIndex + 1,
      pageSize: pagination.pageSize,
      sortBy: "createdAt",
      sortOrder: "DESC",
      // React Query cache key per kind selection ("ALL" when unfiltered).
      tab: kindFilter ?? "ALL",
      ...(kindFilter ? { bookingType: kindFilter } : {}),
      // Server-side free-text search (booking ref, customer, contract ref).
      ...(debouncedQuery.trim() ? { search: debouncedQuery.trim() } : {}),
      ...(statusFilter.length ? { statuses: statusFilter.join(",") } : {}),
      ...(directionFilter ? { tradeDirection: directionFilter } : {}),
      ...(freightTypeFilter ? { freightType: freightTypeFilter } : {}),
      ...(paymentStatusFilter ? { paymentStatus: paymentStatusFilter } : {}),
      ...(ownershipFilter
        ? { isGovernment: ownershipFilter as "true" | "false" }
        : {}),
      ...(originYardFilter ? { originYardId: originYardFilter } : {}),
      ...(destinationYardFilter
        ? { destinationYardId: destinationYardFilter }
        : {}),
      ...(createdFrom ? { createdFrom: startOfDayIso(createdFrom) } : {}),
      ...(createdTo ? { createdTo: endOfDayIso(createdTo) } : {}),
      ...(scheduledFrom ? { scheduledFrom: startOfDayIso(scheduledFrom) } : {}),
      ...(scheduledTo ? { scheduledTo: endOfDayIso(scheduledTo) } : {}),
    };
  }, [
    pagination.pageIndex,
    pagination.pageSize,
    kindFilter,
    debouncedQuery,
    statusFilter,
    directionFilter,
    freightTypeFilter,
    paymentStatusFilter,
    ownershipFilter,
    originYardFilter,
    destinationYardFilter,
    createdFrom,
    createdTo,
    scheduledFrom,
    scheduledTo,
  ]);

  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);

  // Yard options for the origin/destination filters (shared routes reference list).
  const { data: yardRefs } = useQuery(
    api.routes.yards.queryOptions({ staleTime: 5 * 60_000 }),
  );
  const yardOptions = useMemo(
    () =>
      (yardRefs ?? []).map((y) => ({
        value: y.id,
        label: y.label ?? y.code,
      })),
    [yardRefs],
  );

  const resetPage = useCallback(() => {
    setPagination({ pageIndex: 0, pageSize: pagination.pageSize });
  }, [setPagination, pagination.pageSize]);

  const activeFilterCount =
    (kindFilter ? 1 : 0) +
    (statusFilter.length ? 1 : 0) +
    (directionFilter ? 1 : 0) +
    (freightTypeFilter ? 1 : 0) +
    (paymentStatusFilter ? 1 : 0) +
    (ownershipFilter ? 1 : 0) +
    (originYardFilter ? 1 : 0) +
    (destinationYardFilter ? 1 : 0) +
    (createdFrom || createdTo ? 1 : 0) +
    (scheduledFrom || scheduledTo ? 1 : 0);

  const clearFilters = useCallback(() => {
    setKindFilter(null);
    setStatusFilter([]);
    setDirectionFilter(null);
    setFreightTypeFilter(null);
    setPaymentStatusFilter(null);
    setOwnershipFilter(null);
    setOriginYardFilter(null);
    setDestinationYardFilter(null);
    setCreatedFrom(null);
    setCreatedTo(null);
    setScheduledFrom(null);
    setScheduledTo(null);
    resetPage();
  }, [resetPage]);

  // Search is applied server-side (via the `search` filter param) — no
  // client-side filtering here.
  const rows = useMemo(
    () => (data?.items ?? []).map(toBookingListRow),
    [data?.items],
  );

  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 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: "contract",
      header: () => <span className={bookingTable.headerCell}>Contract</span>,
      cell: ({ row }) => {
        const ref = row.original.contractReference;
        return (
          <div className="py-1">
            {ref ? (
              // Fall back to plain text when the id is missing — the reference is
              // still worth showing, it just has nowhere to link to.
              (row.original.contractId ? (
                <ContractReferenceLink
                  contractId={row.original.contractId}
                  contractReference={ref}
                  className="truncate font-mono text-xs text-foreground underline underline-offset-2 hover:text-primary"
                />
              ) : (
                <span className="truncate font-mono text-xs text-foreground">{ref}</span>
              ))
            ) : (
              <span className="text-xs text-muted-foreground">—</span>
            )}
          </div>
        );
      },
    },
    {
      id: "bookingKind",
      header: () => <span className={bookingTable.headerCell}>Type</span>,
      cell: ({ row }) => {
        const isGeneral = row.original.bookingKind === "GENERAL_CONTRACT";
        return (
          <div className="py-1">
            <Badge
              variant={isGeneral ? "secondary" : "outline"}
              className="h-5 px-1.5 text-[10px] font-medium"
            >
              {isGeneral ? "General" : "One-time"}
            </Badge>
          </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: "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",
              },
            ]}
          />

          {/* Status tabs replaced by booking-kind tabs (one-time / general). The
              old BookingStatusTabs is commented out — status is now a filter select.
          <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%">
                <Stack gap="sm">
                  <Group justify="space-between" gap="md" wrap="wrap">
                    <TextInput
                      placeholder="Search booking, contract or customer…"
                      leftSection={<Search size={18} />}
                      value={query}
                      onChange={(e) => {
                        setQuery(e.target.value);
                        resetPage();
                      }}
                      rightSection={
                        query && (
                          <ActionIcon
                            size="sm"
                            color="gray"
                            radius="md"
                            variant="transparent"
                            onClick={() => {
                              setQuery("");
                              resetPage();
                            }}
                          >
                            <X size={16} />
                          </ActionIcon>
                        )
                      }
                      style={{ flex: 1, minWidth: "200px" }}
                      radius="lg"
                    />
                    <Text size="sm" c="dimmed">
                      {total} record{total !== 1 ? "s" : ""}
                    </Text>
                  </Group>
                  <Group gap="sm" wrap="wrap">
                    <Select
                      placeholder="All booking types"
                      data={BOOKING_KIND_OPTIONS}
                      value={kindFilter}
                      onChange={(v) => {
                        setKindFilter((v as BookingKind | null) ?? null);
                        resetPage();
                      }}
                      clearable
                      radius="lg"
                      style={{ minWidth: 190 }}
                    />
                    <MultiSelect
                      placeholder={statusFilter.length ? undefined : "All statuses"}
                      data={STATUS_OPTIONS}
                      value={statusFilter}
                      onChange={(v) => {
                        setStatusFilter(v);
                        resetPage();
                      }}
                      clearable
                      searchable
                      radius="lg"
                      style={{ minWidth: 220 }}
                    />
                    <Select
                      placeholder="All origins"
                      data={yardOptions}
                      value={originYardFilter}
                      onChange={(v) => {
                        setOriginYardFilter(v);
                        resetPage();
                      }}
                      clearable
                      searchable
                      radius="lg"
                      style={{ minWidth: 180 }}
                    />
                    <Select
                      placeholder="All destinations"
                      data={yardOptions}
                      value={destinationYardFilter}
                      onChange={(v) => {
                        setDestinationYardFilter(v);
                        resetPage();
                      }}
                      clearable
                      searchable
                      radius="lg"
                      style={{ minWidth: 180 }}
                    />
                    <Select
                      placeholder="All directions"
                      data={TRADE_DIRECTION_OPTIONS}
                      value={directionFilter}
                      onChange={(v) => {
                        setDirectionFilter(v);
                        resetPage();
                      }}
                      clearable
                      radius="lg"
                      style={{ minWidth: 150 }}
                    />
                    <Select
                      placeholder="All freight types"
                      data={FREIGHT_TYPE_OPTIONS}
                      value={freightTypeFilter}
                      onChange={(v) => {
                        setFreightTypeFilter(v);
                        resetPage();
                      }}
                      clearable
                      radius="lg"
                      style={{ minWidth: 150 }}
                    />
                  </Group>
                  <Group gap="sm" wrap="wrap">
                    <Select
                      placeholder="All payment statuses"
                      data={PAYMENT_STATUS_OPTIONS}
                      value={paymentStatusFilter}
                      onChange={(v) => {
                        setPaymentStatusFilter(v);
                        resetPage();
                      }}
                      clearable
                      radius="lg"
                      style={{ minWidth: 180 }}
                    />
                    <Select
                      placeholder="Gov / Private"
                      data={OWNERSHIP_OPTIONS}
                      value={ownershipFilter}
                      onChange={(v) => {
                        setOwnershipFilter(v);
                        resetPage();
                      }}
                      clearable
                      radius="lg"
                      style={{ minWidth: 140 }}
                    />
                    <DateInput
                      placeholder="Created from"
                      value={createdFrom}
                      onChange={(v) => {
                        setCreatedFrom(v ? new Date(v) : null);
                        resetPage();
                      }}
                      maxDate={createdTo ?? undefined}
                      clearable
                      radius="lg"
                      style={{ minWidth: 140 }}
                    />
                    <DateInput
                      placeholder="Created to"
                      value={createdTo}
                      onChange={(v) => {
                        setCreatedTo(v ? new Date(v) : null);
                        resetPage();
                      }}
                      minDate={createdFrom ?? undefined}
                      clearable
                      radius="lg"
                      style={{ minWidth: 140 }}
                    />
                    <DateInput
                      placeholder="Scheduled from"
                      value={scheduledFrom}
                      onChange={(v) => {
                        setScheduledFrom(v ? new Date(v) : null);
                        resetPage();
                      }}
                      maxDate={scheduledTo ?? undefined}
                      clearable
                      radius="lg"
                      style={{ minWidth: 150 }}
                    />
                    <DateInput
                      placeholder="Scheduled to"
                      value={scheduledTo}
                      onChange={(v) => {
                        setScheduledTo(v ? new Date(v) : null);
                        resetPage();
                      }}
                      minDate={scheduledFrom ?? undefined}
                      clearable
                      radius="lg"
                      style={{ minWidth: 150 }}
                    />
                    {activeFilterCount > 0 ? (
                      <Button
                        variant="subtle"
                        color="gray"
                        radius="lg"
                        leftSection={<FilterX size={16} />}
                        onClick={clearFilters}
                      >
                        Clear filters ({activeFilterCount})
                      </Button>
                    ) : null}
                  </Group>
                </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>
  );
}
