import { Fragment, useMemo, useState } from "react";
import { useNavigate } from "react-router-dom";
import { useQuery } from "@tanstack/react-query";
import {
  Badge,
  Box,
  Button,
  Center,
  Group,
  Loader,
  Paper,
  Popover,
  Select,
  Stack,
  Table,
  Text,
  TextInput,
  Title,
} from "@mantine/core";
import { useDebouncedValue } from "@mantine/hooks";
import {
  AlertTriangle,
  CheckCircle2,
  ChevronDown,
  ChevronLeft,
  ChevronRight,
  FileStack,
  Inbox,
  Package,
  Plus,
  Search,
  Timer,
  Weight,
  X,
} from "lucide-react";

import useAuth from "@/hooks/useAuth";
import { api } from "@/services/api";
import { ContractCustomerAction } from "@/components/customer-actions/ContractCustomerAction";
import type { ContractListFilter } from "@/services/contracts.service";
import type { Freight } from "@edr/types";
import { usePagination } from "@edr/ui-common";
import {
  BORDER,
  ContractDocButton,
  ContractExpiryBadge,
  ContractStatusBadge,
  GREEN,
  INK,
  MUTED,
  StatCard,
} from "./contract-ui";
import { ContractStepBanner } from "./ContractStepBanner";
import "./contracts-table.css";

function primaryRoute(contract: Freight.IContract) {
  const route = contract.routes?.[0];
  return {
    origin: route?.originYard?.label ?? "—",
    destination: route?.destinationYard?.label ?? "—",
    count: contract.routes?.length ?? 0,
  };
}

export default function ContractsList() {
  const navigate = useNavigate();
  const { company } = useAuth();
  const { pagination, setPagination } = usePagination({ pageSize: 10 });
  const [query, setQuery] = useState("");
  const [debouncedQuery] = useDebouncedValue(query, 300);
  const [disclaimerOpen, setDisclaimerOpen] = useState(false);
  const [freightFilter, setFreightFilter] = useState<string | null>(null);
  const [kindFilter, setKindFilter] = useState<string | null>(null);
  const [createdFrom, setCreatedFrom] = useState<string>("");
  const [createdTo, setCreatedTo] = useState<string>("");
  const [expanded, setExpanded] = useState<Set<string>>(new Set());

  // A contract can only be created under an approved profile — NewContractPage
  // blocks every operation whose profile isn't "active". With none approved the
  // page is reachable but unusable, so warn before sending the user there.
  const profiles = company?.company?.companyProfiles ?? [];
  const noActiveProfile =
    profiles.length > 0 && !profiles.some((p) => p.status === "active");

  const openNewContract = () =>
    navigate("/contracts/new", { state: { fresh: true } });

  const toggleExpanded = (id: string) =>
    setExpanded((prev) => {
      const nextSet = new Set(prev);
      if (nextSet.has(id)) nextSet.delete(id);
      else nextSet.add(id);
      return nextSet;
    });

  const resetPage = () =>
    setPagination({ pageIndex: 0, pageSize: pagination.pageSize });
  const hasExtraFilters =
    !!freightFilter || !!kindFilter || !!createdFrom || !!createdTo;
  const clearExtraFilters = () => {
    setFreightFilter(null);
    setKindFilter(null);
    setCreatedFrom("");
    setCreatedTo("");
    resetPage();
  };

  const filter: ContractListFilter = useMemo(
    () => ({
      contractKind: kindFilter ?? undefined,
      freightType: freightFilter ?? undefined,
      createdFrom: createdFrom || undefined,
      createdTo: createdTo ? `${createdTo}T23:59:59.999Z` : undefined,
      // Server-side free-text search (contract reference, company name).
      search: debouncedQuery.trim() || undefined,
      page: pagination.pageIndex + 1,
      pageSize: pagination.pageSize,
      sortBy: "createdAt",
      sortOrder: "DESC",
    }),
    [
      kindFilter,
      freightFilter,
      createdFrom,
      createdTo,
      debouncedQuery,
      pagination.pageIndex,
      pagination.pageSize,
    ],
  );

  const { data, isLoading, isError } = useQuery(
    api.contracts.list.queryOptions({ input: filter }),
  );

  // Bookings have no embedded link on the contract list, so cross-reference
  // them to decide Book / Re-book per row (see getContractBookingAction).
  const { data: bookingsData } = useQuery(
    api.bookings.list.queryOptions({
      input: { sortBy: "createdAt", sortOrder: "DESC" },
    }),
  );
  const bookings = bookingsData?.items ?? [];

  // Search + pagination are fully server-side — rows are the page as returned.
  const rows = data?.items ?? [];

  const stats = useMemo(() => {
    const items = data?.items ?? [];
    const active = items.filter((c) =>
      [
        "CONTRACT_ACTIVE",
        "FULLY_EXECUTED",
        "ACTIVE_SHIPMENT_IN_PROGRESS",
      ].includes(c.status),
    ).length;
    const pending = items.filter((c) =>
      [
        "SUBMITTED",
        "PENDING_APPROVAL",
        "APPROVED",
        "APPROVED_PENDING_SIGNATURE",
        "CONTRACT_READY",
        "SIGNED_CUSTOMER",
        "AWAITING_CLEARANCE_DOCUMENTS",
        "CLEARANCE_UNDER_REVIEW",
        "CLEARANCE_READY_FOR_BOOKING",
      ].includes(c.status),
    ).length;
    const total = data?.meta?.total ?? items.length;
    return { active, pending, total };
  }, [data]);

  const total = data?.meta?.total ?? data?.items?.length ?? 0;
  const pageCount = Math.max(1, Math.ceil(total / pagination.pageSize));
  const pageIndex = pagination.pageIndex;
  const start = total === 0 ? 0 : pageIndex * pagination.pageSize + 1;
  const end = Math.min((pageIndex + 1) * pagination.pageSize, total);

  const goToPage = (i: number) =>
    setPagination({
      pageIndex: Math.max(0, Math.min(i, pageCount - 1)),
      pageSize: pagination.pageSize,
    });

  return (
    <Box style={{ padding: "28px 32px 32px" }}>
      <Stack gap="lg">
        {/* Header */}
        <Group justify="space-between" align="center" wrap="wrap" gap="md">
          <Title
            order={1}
            fw={800}
            fz={26}
            style={{ letterSpacing: "-0.01em" }}
          >
            Contracts
          </Title>
          <Popover
            opened={disclaimerOpen}
            onChange={setDisclaimerOpen}
            position="bottom-end"
            width={340}
            radius="md"
            shadow="md"
            withArrow
            trapFocus
          >
            <Popover.Target>
              <Button
                color="edr-green"
                radius="md"
                size="md"
                leftSection={<Plus size={16} />}
                onClick={() =>
                  noActiveProfile
                    ? setDisclaimerOpen((o) => !o)
                    : openNewContract()
                }
                styles={{
                  root: { fontWeight: 600, height: 42, paddingInline: 18 },
                }}
              >
                New Contract
              </Button>
            </Popover.Target>
            <Popover.Dropdown>
              <Stack gap="sm">
                <Group gap={8} wrap="nowrap" align="flex-start">
                  <AlertTriangle
                    size={18}
                    color="var(--mantine-color-edr-accent-6)"
                    style={{ flexShrink: 0, marginTop: 1 }}
                  />
                  <Text fz={14} fw={700} style={{ color: INK }}>
                    None of your profiles are active yet
                  </Text>
                </Group>

                <Text fz={13} c="dimmed">
                  Contracts can only be created under a profile EDR has
                  approved. You can continue, but every operation stays locked
                  until at least one profile is approved.
                </Text>
              </Stack>
            </Popover.Dropdown>
          </Popover>
        </Group>

        {/* Summary strip */}
        <Group gap="md" wrap="wrap" align="stretch">
          <StatCard
            label="Active"
            hint="ready to ship"
            value={stats.active}
            icon={CheckCircle2}
            color="edr-green"
          />
          <StatCard
            label="In progress"
            hint="setup / signing / clearance"
            value={stats.pending}
            icon={Timer}
            color="edr-accent"
          />
          <StatCard
            label="Total contracts"
            value={stats.total}
            icon={FileStack}
            color="violet"
          />
        </Group>

        {/* Search + filters */}
        <Paper withBorder radius="lg" p="sm" style={{ borderColor: BORDER }}>
          <Group gap={10} wrap="wrap" align="center">
            <TextInput
              placeholder="Search by reference or customer…"
              leftSection={<Search size={16} />}
              value={query}
              onChange={(e) => {
                setQuery(e.currentTarget.value);
                resetPage();
              }}
              radius="md"
              styles={{ input: { height: 42 } }}
              style={{ flex: 1, minWidth: 220, maxWidth: 360 }}
            />
            <Select
              placeholder="Any kind"
              data={[
                { value: "ONE_TIME", label: "One-Time" },
                { value: "GENERAL", label: "General" },
              ]}
              value={kindFilter}
              onChange={(v) => {
                setKindFilter(v);
                resetPage();
              }}
              clearable
              radius="md"
              comboboxProps={{ withinPortal: true }}
              style={{ width: 140 }}
              styles={{ input: { height: 42 } }}
              aria-label="Filter by contract kind"
            />
            <Select
              placeholder="Any cargo"
              data={[
                { value: "CONTAINER", label: "Container" },
                { value: "BULK", label: "Bulk" },
              ]}
              value={freightFilter}
              onChange={(v) => {
                setFreightFilter(v);
                resetPage();
              }}
              clearable
              radius="md"
              comboboxProps={{ withinPortal: true }}
              style={{ width: 150 }}
              styles={{ input: { height: 42 } }}
              aria-label="Filter by cargo type"
            />
            <TextInput
              type="date"
              value={createdFrom}
              onChange={(e) => {
                setCreatedFrom(e.currentTarget.value);
                resetPage();
              }}
              radius="md"
              style={{ width: 152 }}
              styles={{ input: { height: 42 } }}
              aria-label="Created from"
            />
            <TextInput
              type="date"
              value={createdTo}
              onChange={(e) => {
                setCreatedTo(e.currentTarget.value);
                resetPage();
              }}
              radius="md"
              style={{ width: 152 }}
              styles={{ input: { height: 42 } }}
              aria-label="Created to"
            />
            {hasExtraFilters && (
              <Button
                variant="subtle"
                color="gray"
                radius="md"
                leftSection={<X size={14} />}
                onClick={clearExtraFilters}
                styles={{ root: { fontWeight: 600 } }}
              >
                Clear
              </Button>
            )}
          </Group>
        </Paper>

        {/* Table */}
        <Paper
          withBorder
          radius="lg"
          style={{ borderColor: BORDER, overflow: "hidden" }}
        >
          <Box style={{ overflowX: "auto" }}>
            <Table
              className="edr-contracts-table"
              verticalSpacing={14}
              horizontalSpacing={10}
              highlightOnHover
              highlightOnHoverColor="#F4FBF8"
              styles={{
                // Sticky positioning, z-index and wrapping live in
                // contracts-table.css — Mantine's `styles` prop emits inline
                // styles, which would outrank the sticky action column there.
                th: {
                  fontSize: 11,
                  fontWeight: 700,
                  letterSpacing: "0.05em",
                  textTransform: "uppercase",
                  color: MUTED,
                  background: "#F8FAFC",
                  borderBottom: `1px solid ${BORDER}`,
                },
                tr: {
                  transition: "background-color 120ms ease",
                },
                td: {
                  borderBottom: `1px solid ${BORDER}`,
                  verticalAlign: "middle",
                },
              }}
            >
              <Table.Thead>
                <Table.Tr>
                  <Table.Th style={{ width: 44 }} aria-label="Expand" />
                  <Table.Th>Contract</Table.Th>
                  <Table.Th>Type</Table.Th>
                  <Table.Th>Cargo</Table.Th>
                  <Table.Th>Route</Table.Th>
                  <Table.Th>Trade</Table.Th>
                  <Table.Th>Customs</Table.Th>
                  <Table.Th>Currency</Table.Th>
                  <Table.Th>Created</Table.Th>
                  <Table.Th>Valid Until</Table.Th>
                  <Table.Th>Status</Table.Th>
                  <Table.Th ta="right">Action</Table.Th>
                </Table.Tr>
              </Table.Thead>
              <Table.Tbody>
                {isLoading && (
                  <Table.Tr>
                    <Table.Td colSpan={12}>
                      <Center py={48}>
                        <Loader color="edr-green" size="sm" />
                      </Center>
                    </Table.Td>
                  </Table.Tr>
                )}

                {!isLoading && isError && (
                  <Table.Tr>
                    <Table.Td colSpan={12}>
                      <Center py={48}>
                        <Text fz={13} c="red">
                          Failed to load contracts. Please try again.
                        </Text>
                      </Center>
                    </Table.Td>
                  </Table.Tr>
                )}

                {!isLoading && !isError && rows.length === 0 && (
                  <Table.Tr>
                    <Table.Td colSpan={12}>
                      <Stack align="center" gap={8} py={48}>
                        <Inbox
                          size={26}
                          color={MUTED}
                          style={{ opacity: 0.5 }}
                        />
                        <Text fz={13} c="dimmed">
                          No contracts yet. Create one from New Contract.
                        </Text>
                      </Stack>
                    </Table.Td>
                  </Table.Tr>
                )}

                {!isLoading &&
                  !isError &&
                  rows.map((c) => {
                    const isGeneral = c.contractKind === "GENERAL";
                    const isContainer = c.freightType === "CONTAINER";
                    const { origin, destination, count } = primaryRoute(c);
                    const dir = c.tradeDirection;
                    const tradeLabel = dir
                      ? dir.charAt(0) + dir.slice(1).toLowerCase()
                      : "—";
                    const isOpen = expanded.has(c.id);
                    return (
                      <Fragment key={c.id}>
                        <Table.Tr
                          // Read by contracts-table.css to keep the sticky
                          // action cell's opaque background in step with the row.
                          data-expanded={isOpen ? "true" : undefined}
                          style={{
                            cursor: "pointer",
                            background: isOpen ? "#F4FBF8" : undefined,
                          }}
                          onClick={() => navigate(`/contracts/${c.id}`)}
                        >
                          <Table.Td>
                            <Box
                              component="button"
                              aria-label={
                                isOpen ? "Hide progress" : "Show progress"
                              }
                              aria-expanded={isOpen}
                              onClick={(e) => {
                                e.stopPropagation();
                                toggleExpanded(c.id);
                              }}
                              style={{
                                display: "flex",
                                alignItems: "center",
                                justifyContent: "center",
                                width: 28,
                                height: 28,
                                borderRadius: 8,
                                border: `1px solid ${BORDER}`,
                                background: isOpen ? GREEN : "#FFFFFF",
                                color: isOpen ? "#FFFFFF" : MUTED,
                                cursor: "pointer",
                                transition: "all 140ms ease",
                              }}
                            >
                              <ChevronDown
                                size={16}
                                style={{
                                  transform: isOpen ? "rotate(180deg)" : "none",
                                  transition: "transform 160ms ease",
                                }}
                              />
                            </Box>
                          </Table.Td>
                          <Table.Td>
                            <Text fz={14} fw={700} style={{ color: INK }}>
                              {c.reference}
                            </Text>
                            <Text fz={12} c="dimmed">
                              {isContainer ? "Containerised" : "Bulk"}
                            </Text>
                          </Table.Td>
                          <Table.Td>
                            <Badge
                              variant="light"
                              color={isGeneral ? "edr-green" : "gray"}
                              radius="sm"
                            >
                              {isGeneral ? "General" : "One-Time"}
                            </Badge>
                          </Table.Td>
                          <Table.Td>
                            <Group gap={7} wrap="nowrap" align="center">
                              {isContainer ? (
                                <Package size={15} color={MUTED} />
                              ) : (
                                <Weight size={15} color={MUTED} />
                              )}
                              <Text fz={13} style={{ color: INK }}>
                                {isContainer ? "Container" : "Bulk"}
                              </Text>
                            </Group>
                          </Table.Td>
                          <Table.Td>
                            <Text fz={13} style={{ color: INK }}>
                              {origin}{" "}
                              <Text span c="dimmed">
                                →
                              </Text>{" "}
                              {destination}
                              {count > 1 && (
                                <Text span c="dimmed" fz={12}>
                                  {" "}
                                  +{count - 1}
                                </Text>
                              )}
                            </Text>
                          </Table.Td>
                          <Table.Td>
                            <Text
                              fz={13}
                              c={dir ? undefined : "dimmed"}
                              style={{ color: dir ? INK : undefined }}
                            >
                              {tradeLabel}
                            </Text>
                          </Table.Td>
                          <Table.Td>
                            <Badge
                              variant="light"
                              color={c.customsClearingEnabled ? "edr-green" : "gray"}
                              radius="sm"
                            >
                              {c.customsClearingEnabled ? "With customs" : "Without"}
                            </Badge>
                          </Table.Td>
                          <Table.Td>
                            <Text fz={13} style={{ color: INK }}>
                              {c.paymentCurrency ?? "—"}
                            </Text>
                          </Table.Td>
                          <Table.Td>
                            <Text
                              fz={13}
                              c={c.createdAt ? undefined : "dimmed"}
                              style={{ color: c.createdAt ? INK : undefined }}
                            >
                              {c.createdAt
                                ? new Date(c.createdAt).toLocaleDateString()
                                : "—"}
                            </Text>
                          </Table.Td>
                          <Table.Td>
                            <Text
                              fz={13}
                              c={c.contractValidUntil ? undefined : "dimmed"}
                              style={{
                                color: c.contractValidUntil ? INK : undefined,
                              }}
                            >
                              {c.contractValidUntil
                                ? new Date(
                                  c.contractValidUntil,
                                ).toLocaleDateString()
                                : "—"}
                            </Text>
                            {/* Countdown once the contract is inside the notice
                                window — renders nothing before that. */}
                            <ContractExpiryBadge contract={c} />
                          </Table.Td>
                          <Table.Td>
                            <ContractStatusBadge status={c.status} />
                          </Table.Td>
                          <Table.Td>
                            <Group justify="flex-end" gap={8} wrap="nowrap">
                              <ContractDocButton
                                contract={c}
                                onClick={(e) => e.stopPropagation()}
                              />
                              <ContractCustomerAction
                                contract={c}
                                bookings={bookings}
                                size="sm"
                                listStyle
                              />
                            </Group>
                          </Table.Td>
                        </Table.Tr>
                        {isOpen && (
                          <Table.Tr style={{ background: "#F4FBF8" }}>
                            <Table.Td
                              colSpan={12}
                              style={{ padding: "6px 20px 18px" }}
                            >
                              <ContractStepBanner contract={c} />
                            </Table.Td>
                          </Table.Tr>
                        )}
                      </Fragment>
                    );
                  })}
              </Table.Tbody>
            </Table>
          </Box>

          {/* Pagination footer */}
          {!isLoading && !isError && rows.length > 0 && (
            <Group
              justify="space-between"
              align="center"
              wrap="wrap"
              gap="md"
              px={20}
              py={14}
              style={{
                borderTop: `1px solid ${BORDER}`,
                background: "#FCFDFE",
              }}
            >
              <Group gap={10} align="center">
                <Text fz={13} c="dimmed">
                  Rows
                </Text>
                <Select
                  data={["10", "25", "50"]}
                  value={String(pagination.pageSize)}
                  onChange={(v) =>
                    v && setPagination({ pageIndex: 0, pageSize: Number(v) })
                  }
                  radius="md"
                  size="xs"
                  comboboxProps={{ withinPortal: true }}
                  style={{ width: 76 }}
                  allowDeselect={false}
                />
                <Text fz={13} c="dimmed">
                  {start}–{end} of {total}
                </Text>
              </Group>

              <Group gap={6} align="center">
                <PagerButton
                  icon={<ChevronLeft size={16} />}
                  disabled={pageIndex === 0}
                  onClick={() => goToPage(pageIndex - 1)}
                  ariaLabel="Previous page"
                />
                {pageNumbers(pageIndex, pageCount).map((p, i) =>
                  p === "…" ? (
                    <Text key={`gap-${i}`} fz={13} c="dimmed" px={4}>
                      …
                    </Text>
                  ) : (
                    <PageChip
                      key={p}
                      page={p}
                      active={p === pageIndex}
                      onClick={() => goToPage(p)}
                    />
                  ),
                )}
                <PagerButton
                  icon={<ChevronRight size={16} />}
                  disabled={pageIndex >= pageCount - 1}
                  onClick={() => goToPage(pageIndex + 1)}
                  ariaLabel="Next page"
                />
              </Group>
            </Group>
          )}
        </Paper>
      </Stack>
    </Box>
  );
}

/** Compact page-number window with ellipses: 1 … 4 5 6 … 12. */
function pageNumbers(active: number, count: number): (number | "…")[] {
  if (count <= 7) return Array.from({ length: count }, (_, i) => i);
  const out: (number | "…")[] = [0];
  const lo = Math.max(1, active - 1);
  const hi = Math.min(count - 2, active + 1);
  if (lo > 1) out.push("…");
  for (let i = lo; i <= hi; i++) out.push(i);
  if (hi < count - 2) out.push("…");
  out.push(count - 1);
  return out;
}

function PageChip({
  page,
  active,
  onClick,
}: {
  page: number;
  active: boolean;
  onClick: () => void;
}) {
  return (
    <Box
      component="button"
      onClick={onClick}
      style={{
        minWidth: 32,
        height: 32,
        padding: "0 8px",
        borderRadius: 9,
        border: `1px solid ${active ? GREEN : BORDER}`,
        background: active ? GREEN : "#FFFFFF",
        color: active ? "#FFFFFF" : INK,
        fontSize: 13,
        fontWeight: active ? 700 : 600,
        cursor: "pointer",
        transition: "all 120ms ease",
      }}
    >
      {page + 1}
    </Box>
  );
}

function PagerButton({
  icon,
  disabled,
  onClick,
  ariaLabel,
}: {
  icon: React.ReactNode;
  disabled: boolean;
  onClick: () => void;
  ariaLabel: string;
}) {
  return (
    <Box
      component="button"
      aria-label={ariaLabel}
      onClick={onClick}
      disabled={disabled}
      style={{
        width: 32,
        height: 32,
        display: "flex",
        alignItems: "center",
        justifyContent: "center",
        borderRadius: 9,
        border: `1px solid ${BORDER}`,
        background: "#FFFFFF",
        color: disabled ? "#C2CCD6" : INK,
        cursor: disabled ? "not-allowed" : "pointer",
        opacity: disabled ? 0.6 : 1,
        transition: "all 120ms ease",
      }}
    >
      {icon}
    </Box>
  );
}
