import { directionLabel } from "@/lib/utils";
import {
  ActionIcon,
  Box,
  Button,
  Card,
  Group,
  MultiSelect,
  Select,
  Stack,
  Text,
  TextInput,
  ThemeIcon,
} from "@mantine/core";
import { DateInput } from "@mantine/dates";
import { useDebouncedValue } from "@mantine/hooks";
import {
  AlertTriangle,
  ArrowRight,
  CalendarClock,
  CheckCircle2,
  Clock,
  FileText,
  FilterX,
  Inbox,
  LayoutList,
  RefreshCw,
  Repeat,
  Search,
  User,
  X,
} from "lucide-react";
import { useCallback, useMemo, useState } from "react";
import { useNavigate } from "react-router-dom";

import { ContractApprovalProgressCell } from "@/components/contracts/ContractApprovalProgressCell";
import { ContractStatusBadge } from "@/components/contracts/ContractStatusBadge";
import {
  ContractStatusTabs,
  type ContractStatusTabKey,
} from "@/components/contracts/ContractStatusTabs";
import { bookingTable } from "@/components/bookings/booking-ui.styles";
import { KpiStrip, PageContainer, PageHeader } from "@/components/page";
import {
  CONTRACT_LIST_TABS,
  CONTRACT_STATUS_STYLES,
} from "@/features/contracts/contract-status.config";
import {
  getStaffRowAction,
  toContractListRow,
  type ContractListRow,
} from "@/features/contracts/mapContractListRow";
import {
  useContractList,
  useContractListSummary,
} from "@/hooks/contracts/useContracts";
import type { ContractListFilter } from "@/services/contracts.service";
import {
  Badge,
  DataTable,
  DataTableFooter,
  usePagination,
  type ColumnDef,
} from "@edr/ui-common";

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

/** Statuses selectable in the status filter for a given tab ("all" → every tab status). */
function getStatusOptionsForTab(
  tab: ContractStatusTabKey,
): { value: string; label: string }[] {
  const match = CONTRACT_LIST_TABS.find((t) => t.key === tab);
  const statuses = match?.statuses?.length
    ? match.statuses
    : CONTRACT_LIST_TABS.flatMap((t) => t.statuses ?? []);
  return statuses.map((s) => ({
    value: s,
    label: CONTRACT_STATUS_STYLES[s]?.label ?? s,
  }));
}

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 CONTRACT_KIND_OPTIONS = [
  { value: "GENERAL", label: "General (recurring)" },
  { value: "ONE_TIME", label: "One-time" },
];

const CURRENCY_OPTIONS = [
  { value: "ETB", label: "ETB" },
  { value: "USD", label: "USD" },
];

/** value = `${sortBy}:${sortOrder}` for the sort Select. */
const SORT_OPTIONS = [
  { value: "createdAt:DESC", label: "Newest first" },
  { value: "createdAt:ASC", label: "Oldest first" },
  { value: "contractValidUntil:ASC", label: "Expiring soonest" },
  { value: "contractValidUntil:DESC", label: "Expiring latest" },
];

/** Every column is 120px wide and wraps its content instead of truncating. */
const COLUMN_WIDTH = 120;
const COLUMN_META = {
  headerClassName: "whitespace-normal break-words",
  cellClassName: "whitespace-normal break-words align-top",
};

/** 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 ContractRequestsPage() {
  const navigate = useNavigate();
  const { pagination, setPagination } = usePagination({ pageSize: 10 });
  const [query, setQuery] = useState("");
  const [debouncedQuery] = useDebouncedValue(query, 300);
  const [activeTab, setActiveTab] = useState<ContractStatusTabKey>("all");
  // Filter controls (empty/null = "all").
  const [statusFilter, setStatusFilter] = useState<string[]>([]);
  const [directionFilter, setDirectionFilter] = useState<string | null>(null);
  const [freightTypeFilter, setFreightTypeFilter] = useState<string | null>(
    null,
  );
  const [kindFilter, setKindFilter] = useState<string | null>(null);
  const [currencyFilter, setCurrencyFilter] = useState<string | null>(null);
  const [createdFrom, setCreatedFrom] = useState<Date | null>(null);
  const [createdTo, setCreatedTo] = useState<Date | null>(null);
  const [sort, setSort] = useState<string>("createdAt:DESC");

  const tabStatuses = getStatusesForTab(activeTab);
  const statusOptions = useMemo(
    () => getStatusOptionsForTab(activeTab),
    [activeTab],
  );

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

  const filter: ContractListFilter = useMemo(() => {
    const [sortBy, sortOrder] = sort.split(":") as [string, "ASC" | "DESC"];
    return {
      page: pagination.pageIndex + 1,
      pageSize: pagination.pageSize,
      sortBy,
      sortOrder,
      tab: activeTab,
      // Server-side free-text search (contract reference, customer name).
      ...(debouncedQuery.trim() ? { search: debouncedQuery.trim() } : {}),
      // Explicit status picks narrow within the tab; otherwise the tab's
      // status group applies.
      ...(statusFilter.length
        ? { statuses: statusFilter.join(",") }
        : tabStatuses
          ? { statuses: tabStatuses }
          : {}),
      ...(directionFilter ? { tradeDirection: directionFilter } : {}),
      ...(freightTypeFilter ? { freightType: freightTypeFilter } : {}),
      ...(kindFilter ? { contractKind: kindFilter } : {}),
      ...(currencyFilter ? { paymentCurrency: currencyFilter } : {}),
      ...(createdFrom ? { createdFrom: startOfDayIso(createdFrom) } : {}),
      ...(createdTo ? { createdTo: endOfDayIso(createdTo) } : {}),
    };
  }, [
    pagination.pageIndex,
    pagination.pageSize,
    activeTab,
    tabStatuses,
    debouncedQuery,
    statusFilter,
    directionFilter,
    freightTypeFilter,
    kindFilter,
    currencyFilter,
    createdFrom,
    createdTo,
    sort,
  ]);

  const activeFilterCount =
    (statusFilter.length ? 1 : 0) +
    (directionFilter ? 1 : 0) +
    (freightTypeFilter ? 1 : 0) +
    (kindFilter ? 1 : 0) +
    (currencyFilter ? 1 : 0) +
    (createdFrom || createdTo ? 1 : 0);

  const clearFilters = useCallback(() => {
    setStatusFilter([]);
    setDirectionFilter(null);
    setFreightTypeFilter(null);
    setKindFilter(null);
    setCurrencyFilter(null);
    setCreatedFrom(null);
    setCreatedTo(null);
    setPagination({ pageIndex: 0, pageSize: pagination.pageSize });
  }, [setPagination, pagination.pageSize]);

  const { data, isLoading, isError, refetch, isFetching } =
    useContractList(filter);
  const {
    data: summary,
    isLoading: summaryLoading,
    refetch: refetchSummary,
  } = useContractListSummary(filter);

  const rows = useMemo(
    () => (data?.items ?? []).map(toContractListRow),
    [data?.items],
  );

  const total = data?.total ?? 0;
  const pageCount = Math.max(1, Math.ceil(total / pagination.pageSize));
  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: ContractListRow) => {
      navigate(`/dashboard/contract-requests/${row.id}`);
    },
    [navigate],
  );

  const columns: ColumnDef<ContractListRow>[] = [
    {
      id: "contract",
      size: COLUMN_WIDTH,
      meta: COLUMN_META,
      header: () => <span className={bookingTable.headerCell}>Customer</span>,
      cell: ({ row }) => {
        const c = row.original;
        return (
          <div className="flex items-center gap-3 py-1.5">
            <div className={bookingTable.rowIcon}>
              <User className="size-4" strokeWidth={1.75} />
            </div>
            <div className="min-w-0">
              <p className="font-medium text-foreground">{c.customerLabel}</p>
              <p className="mt-0.5 flex items-center gap-1 text-xs text-muted-foreground">
                <FileText className="size-3 shrink-0 opacity-70" />
                {c.reference}
              </p>
            </div>
          </div>
        );
      },
    },
    {
      id: "route",
      size: COLUMN_WIDTH,
      meta: COLUMN_META,
      header: () => <span className={bookingTable.headerCell}>Route</span>,
      cell: ({ row }) => {
        const c = 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>{c.originLabel}</span>
              <ArrowRight className="size-3.5 shrink-0 text-muted-foreground" />
              <span>{c.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"
              >
                {directionLabel(c.tradeDirection)}
              </Badge>
              <Badge
                variant="secondary"
                className="h-5 bg-muted/40 px-1.5 text-[10px] font-medium"
              >
                {c.freightType}
              </Badge>
            </div>
          </div>
        );
      },
    },
    {
      id: "status",
      size: COLUMN_WIDTH,
      meta: COLUMN_META,
      header: () => <span className={bookingTable.headerCell}>Status</span>,
      cell: ({ row }) => (
        <div className="py-1">
          <ContractStatusBadge
            status={row.original.status}
            isRenewal={row.original.isRenewal}
          />
        </div>
      ),
    },
    {
      id: "approval",
      size: COLUMN_WIDTH,
      meta: COLUMN_META,
      header: () => <span className={bookingTable.headerCell}>Approval</span>,
      cell: ({ row }) => <ContractApprovalProgressCell row={row.original} />,
    },
    {
      id: "validity",
      size: COLUMN_WIDTH,
      meta: COLUMN_META,
      header: () => <span className={bookingTable.headerCell}>Validity</span>,
      cell: ({ row }) => {
        const c = row.original;
        return (
          <Stack gap={2}>
            <span className="inline-flex items-center gap-1.5 text-sm text-muted-foreground">
              <CalendarClock className="size-3.5" />
              {c.validUntil
                ? `Until ${formatDate(c.validUntil)}`
                : c.validityDays
                  ? `${c.validityDays} days`
                  : "—"}
            </span>
            {c.validFrom ? (
              <Text size="xs" c="dimmed">
                From {formatDate(c.validFrom)}
              </Text>
            ) : null}
          </Stack>
        );
      },
    },
    {
      id: "kind",
      size: COLUMN_WIDTH,
      meta: COLUMN_META,
      header: () => <span className={bookingTable.headerCell}>Kind</span>,
      cell: ({ row }) => {
        const isGeneral = row.original.contractKind === "GENERAL";
        return (
          <Badge
            variant="outline"
            className="h-5 border-border/50 bg-background/50 px-1.5 text-[10px] font-medium uppercase"
          >
            {isGeneral ? (
              <span className="inline-flex items-center gap-1">
                <Repeat className="size-3" /> General
              </span>
            ) : (
              "One-time"
            )}
          </Badge>
        );
      },
    },
    {
      id: "actions",
      size: COLUMN_WIDTH,
      meta: COLUMN_META,
      header: () => <span className={bookingTable.headerCell}>Action</span>,
      cell: ({ row }) => {
        const action = getStaffRowAction(row.original);
        if (!action) return null;
        return (
          <Button
            size="compact-sm"
            radius="md"
            variant={action.variant === "filled" ? "filled" : action.variant}
            color="edr-green"
            onClick={(e) => {
              // Don't let the row-click navigation fire as well.
              e.stopPropagation();
              navigate(action.to(row.original.id));
            }}
          >
            {action.label}
          </Button>
        );
      },
    },
  ];

  return (
    <PageContainer>
      <Stack gap="lg">
        <PageHeader
          title="Contract requests"
          subtitle="Review, approve, and execute freight contract requests."
          action={
            <ActionIcon
              variant="default"
              size="lg"
              radius="md"
              loading={isFetching}
              onClick={handleRefresh}
              aria-label="Refresh"
            >
              <RefreshCw size={16} />
            </ActionIcon>
          }
        />

        <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: "Closed",
              value: tabCounts?.closed ?? 0,
              icon: CheckCircle2,
              color: "edr-green",
            },
          ]}
        />

        <ContractStatusTabs
          active={activeTab}
          onChange={(tab) => {
            setActiveTab(tab);
            // Status picks belong to the previous tab's option set — reset.
            setStatusFilter([]);
            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 reference 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"
                  />
                  <Select
                    data={SORT_OPTIONS}
                    value={sort}
                    onChange={(v) => {
                      setSort(v ?? "createdAt:DESC");
                      resetPage();
                    }}
                    allowDeselect={false}
                    radius="lg"
                    style={{ minWidth: 170 }}
                    aria-label="Sort contracts"
                  />
                  <Text size="sm" c="dimmed">
                    {total} record{total !== 1 ? "s" : ""}
                  </Text>
                </Group>
                <Group gap="sm" wrap="wrap">
                  <MultiSelect
                    placeholder={
                      statusFilter.length ? undefined : "All statuses"
                    }
                    data={statusOptions}
                    value={statusFilter}
                    onChange={(v) => {
                      setStatusFilter(v);
                      resetPage();
                    }}
                    clearable
                    searchable
                    radius="lg"
                    style={{ minWidth: 220 }}
                    aria-label="Filter by status"
                  />
                  <Select
                    placeholder="All directions"
                    data={TRADE_DIRECTION_OPTIONS}
                    value={directionFilter}
                    onChange={(v) => {
                      setDirectionFilter(v);
                      resetPage();
                    }}
                    clearable
                    radius="lg"
                    style={{ minWidth: 150 }}
                    aria-label="Filter by trade direction"
                  />
                  <Select
                    placeholder="All freight types"
                    data={FREIGHT_TYPE_OPTIONS}
                    value={freightTypeFilter}
                    onChange={(v) => {
                      setFreightTypeFilter(v);
                      resetPage();
                    }}
                    clearable
                    radius="lg"
                    style={{ minWidth: 160 }}
                    aria-label="Filter by freight type"
                  />
                  <Select
                    placeholder="All kinds"
                    data={CONTRACT_KIND_OPTIONS}
                    value={kindFilter}
                    onChange={(v) => {
                      setKindFilter(v);
                      resetPage();
                    }}
                    clearable
                    radius="lg"
                    style={{ minWidth: 160 }}
                    aria-label="Filter by contract kind"
                  />
                  <Select
                    placeholder="All currencies"
                    data={CURRENCY_OPTIONS}
                    value={currencyFilter}
                    onChange={(v) => {
                      setCurrencyFilter(v);
                      resetPage();
                    }}
                    clearable
                    radius="lg"
                    style={{ minWidth: 140 }}
                    aria-label="Filter by payment currency"
                  />
                  <DateInput
                    placeholder="Created from"
                    value={createdFrom}
                    onChange={(v) => {
                      setCreatedFrom(v ? new Date(v) : null);
                      resetPage();
                    }}
                    maxDate={createdTo ?? undefined}
                    clearable
                    radius="lg"
                    style={{ minWidth: 140 }}
                    aria-label="Created from"
                  />
                  <DateInput
                    placeholder="Created to"
                    value={createdTo}
                    onChange={(v) => {
                      setCreatedTo(v ? new Date(v) : null);
                      resetPage();
                    }}
                    minDate={createdFrom ?? undefined}
                    clearable
                    radius="lg"
                    style={{ minWidth: 140 }}
                    aria-label="Created to"
                  />
                  {activeFilterCount > 0 ? (
                    <Button
                      variant="subtle"
                      color="gray"
                      radius="lg"
                      leftSection={<FilterX size={16} />}
                      onClick={clearFilters}
                    >
                      Clear filters ({activeFilterCount})
                    </Button>
                  ) : null}
                </Group>
              </Stack>
            </Box>

            {showEmpty ? (
              <Stack align="center" gap={8} py={48}>
                <ThemeIcon variant="light" color="gray" radius="xl" size={48}>
                  <Inbox size={22} />
                </ThemeIcon>
                <Text c="dimmed">No contracts match this view.</Text>
              </Stack>
            ) : (
              <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,
                  }}
                  // table-fixed makes the per-column 120px widths stick; without
                  // it auto-layout re-widens columns once cells wrap.
                  containerClassName="border-0 shadow-none bg-transparent [&_table]:table-fixed [&_table]:min-w-[840px]"
                  footer={DataTableFooter}
                />
              </Box>
            )}
          </Stack>
        </Card>
      </Stack>
    </PageContainer>
  );
}
