import { useMemo, useState } from "react";
import { useNavigate } from "react-router-dom";
import { useQuery } from "@tanstack/react-query";
import {
  Box,
  Button,
  Center,
  Group,
  Loader,
  Paper,
  Select,
  Stack,
  Table,
  Text,
  TextInput,
  Title,
} from "@mantine/core";
import {
  AlertTriangle,
  ChevronLeft,
  ChevronRight,
  CreditCard,
  Eye,
  FileStack,
  Inbox,
  Receipt,
  Search,
  Wallet,
  X,
} from "lucide-react";
import { Freight } from "@edr/types";

import { api } from "@/services/api";
import { formatCurrency } from "@/lib/currency";
import {
  BORDER,
  GREEN,
  INK,
  MUTED,
  StatCard,
} from "../contracts/contract-ui";
import {
  billedTo,
  fmtDate,
  InvoiceStatusBadge,
  isPayable,
  PAYABLE_STATUSES,
  titleCase,
} from "./invoice-ui";

const PAGE_SIZES = ["10", "25", "50"];

export default function InvoicesList() {
  const navigate = useNavigate();
  const [query, setQuery] = useState("");
  const [statusFilter, setStatusFilter] = useState<string | null>(null);
  const [pageIndex, setPageIndex] = useState(0);
  const [pageSize, setPageSize] = useState(10);

  const { data, isLoading, isError } = useQuery(
    api.invoices.listMy.queryOptions(),
  );

  const all = useMemo(() => data ?? [], [data]);

  const stats = useMemo(() => {
    const outstanding = all.filter((i) =>
      PAYABLE_STATUSES.includes(i.status),
    ).length;
    const overdue = all.filter(
      (i) => i.status === Freight.InvoiceStatus.Overdue,
    ).length;
    return { outstanding, overdue, total: all.length };
  }, [all]);

  const rows = useMemo(() => {
    const q = query.trim().toLowerCase();
    return all.filter((inv) => {
      if (statusFilter && inv.status !== statusFilter) return false;
      if (!q) return true;
      return (
        inv.invoiceNumber.toLowerCase().includes(q) ||
        inv.source.toLowerCase().includes(q) ||
        inv.sourceId.toLowerCase().includes(q) ||
        billedTo(inv).toLowerCase().includes(q)
      );
    });
  }, [all, query, statusFilter]);

  const total = rows.length;
  const pageCount = Math.max(1, Math.ceil(total / pageSize));
  const clampedIndex = Math.min(pageIndex, pageCount - 1);
  const start = total === 0 ? 0 : clampedIndex * pageSize + 1;
  const end = Math.min((clampedIndex + 1) * pageSize, total);
  const pageRows = rows.slice(clampedIndex * pageSize, clampedIndex * pageSize + pageSize);

  const resetPage = () => setPageIndex(0);
  const goToPage = (i: number) =>
    setPageIndex(Math.max(0, Math.min(i, pageCount - 1)));

  const hasFilters = !!query || !!statusFilter;

  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" }}>
            Invoices
          </Title>
        </Group>

        {/* Summary strip */}
        <Group gap="md" wrap="wrap" align="stretch">
          <StatCard
            label="Outstanding"
            hint="awaiting payment"
            value={stats.outstanding}
            icon={Wallet}
            color="edr-accent"
          />
          <StatCard
            label="Overdue"
            hint="past due date"
            value={stats.overdue}
            icon={AlertTriangle}
            color="red"
          />
          <StatCard
            label="Total invoices"
            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 number, source or reference…"
              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: 380 }}
            />
            <Select
              placeholder="Any status"
              data={[
                { value: Freight.InvoiceStatus.Pending, label: "Due" },
                { value: Freight.InvoiceStatus.Overdue, label: "Overdue" },
                { value: Freight.InvoiceStatus.Paid, label: "Paid" },
                { value: Freight.InvoiceStatus.Draft, label: "Draft" },
                { value: Freight.InvoiceStatus.Cancelled, label: "Cancelled" },
                { value: Freight.InvoiceStatus.Refunded, label: "Refunded" },
              ]}
              value={statusFilter}
              onChange={(v) => {
                setStatusFilter(v);
                resetPage();
              }}
              clearable
              radius="md"
              comboboxProps={{ withinPortal: true }}
              style={{ width: 160 }}
              styles={{ input: { height: 42 } }}
              aria-label="Filter by status"
            />
            {hasFilters && (
              <Button
                variant="subtle"
                color="gray"
                radius="md"
                leftSection={<X size={14} />}
                onClick={() => {
                  setQuery("");
                  setStatusFilter(null);
                  resetPage();
                }}
                styles={{ root: { fontWeight: 600 } }}
              >
                Clear
              </Button>
            )}
          </Group>
        </Paper>

        {/* Table */}
        <Paper
          withBorder
          radius="lg"
          style={{ borderColor: BORDER, overflow: "hidden" }}
        >
          <Box style={{ overflowX: "auto" }}>
            <Table
              verticalSpacing={14}
              horizontalSpacing={20}
              highlightOnHover
              highlightOnHoverColor="#F4FBF8"
              styles={{
                th: {
                  fontSize: 11,
                  fontWeight: 700,
                  letterSpacing: "0.05em",
                  textTransform: "uppercase",
                  color: MUTED,
                  background: "#F8FAFC",
                  borderBottom: `1px solid ${BORDER}`,
                  whiteSpace: "nowrap",
                  position: "sticky",
                  top: 0,
                  zIndex: 1,
                },
                tr: { transition: "background-color 120ms ease" },
                td: {
                  borderBottom: `1px solid ${BORDER}`,
                  verticalAlign: "middle",
                },
              }}
            >
              <Table.Thead>
                <Table.Tr>
                  <Table.Th>Invoice</Table.Th>
                  <Table.Th>Billed To</Table.Th>
                  <Table.Th>Source</Table.Th>
                  <Table.Th ta="right">Amount</Table.Th>
                  <Table.Th>Issued</Table.Th>
                  <Table.Th>Due</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={8}>
                      <Center py={48}>
                        <Loader color="edr-green" size="sm" />
                      </Center>
                    </Table.Td>
                  </Table.Tr>
                )}

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

                {!isLoading && !isError && pageRows.length === 0 && (
                  <Table.Tr>
                    <Table.Td colSpan={8}>
                      <Stack align="center" gap={8} py={48}>
                        <Inbox size={26} color={MUTED} style={{ opacity: 0.5 }} />
                        <Text fz={13} c="dimmed">
                          {hasFilters
                            ? "No invoices match your filters."
                            : "No invoices yet."}
                        </Text>
                      </Stack>
                    </Table.Td>
                  </Table.Tr>
                )}

                {!isLoading &&
                  !isError &&
                  pageRows.map((inv) => {
                    const payable = isPayable(inv.status);
                    return (
                      <Table.Tr
                        key={inv.id}
                        style={{ cursor: "pointer" }}
                        onClick={() => navigate(`/billing/${inv.id}`)}
                      >
                        <Table.Td>
                          <Group gap={10} wrap="nowrap" align="center">
                            <Box
                              style={{
                                display: "flex",
                                alignItems: "center",
                                justifyContent: "center",
                                width: 34,
                                height: 34,
                                borderRadius: 9,
                                background: "#E6F7EF",
                                color: GREEN,
                                flexShrink: 0,
                              }}
                            >
                              <Receipt size={16} />
                            </Box>
                            <Box>
                              <Text fz={14} fw={700} style={{ color: INK }}>
                                {inv.invoiceNumber}
                              </Text>
                              <Text fz={12} c="dimmed">
                                {titleCase(inv.type)}
                              </Text>
                            </Box>
                          </Group>
                        </Table.Td>
                        <Table.Td>
                          <Text fz={13} style={{ color: INK }}>
                            {billedTo(inv)}
                          </Text>
                        </Table.Td>
                        <Table.Td>
                          <Text fz={13} style={{ color: INK }}>
                            {titleCase(inv.source)}
                          </Text>
                        </Table.Td>
                        <Table.Td ta="right">
                          <Text fz={13} fw={700} style={{ color: INK }}>
                            {formatCurrency(Number(inv.totalAmount), inv.currency)}
                          </Text>
                        </Table.Td>
                        <Table.Td>
                          <Text
                            fz={13}
                            c={inv.issuedAt ? undefined : "dimmed"}
                            style={{ color: inv.issuedAt ? INK : undefined }}
                          >
                            {fmtDate(inv.issuedAt)}
                          </Text>
                        </Table.Td>
                        <Table.Td>
                          <Text fz={13} style={{ color: INK }}>
                            {fmtDate(inv.dueAt)}
                          </Text>
                        </Table.Td>
                        <Table.Td>
                          <InvoiceStatusBadge status={inv.status} />
                        </Table.Td>
                        <Table.Td>
                          <Group justify="flex-end" gap={8} wrap="nowrap">
                            <Button
                              size="sm"
                              radius="md"
                              h={34}
                              variant={payable ? "filled" : "light"}
                              color="edr-green"
                              leftSection={
                                payable ? (
                                  <CreditCard size={15} />
                                ) : (
                                  <Eye size={15} />
                                )
                              }
                              onClick={(e) => {
                                e.stopPropagation();
                                navigate(`/billing/${inv.id}`);
                              }}
                              styles={{
                                root: {
                                  fontWeight: 600,
                                  fontSize: 13,
                                  paddingInline: 14,
                                  whiteSpace: "nowrap",
                                  boxShadow: payable
                                    ? "0 1px 2px rgba(14,163,113,0.25)"
                                    : "none",
                                },
                              }}
                            >
                              {payable ? "Pay" : "View"}
                            </Button>
                          </Group>
                        </Table.Td>
                      </Table.Tr>
                    );
                  })}
              </Table.Tbody>
            </Table>
          </Box>

          {/* Pagination footer */}
          {!isLoading && !isError && total > 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={PAGE_SIZES}
                  value={String(pageSize)}
                  onChange={(v) => {
                    if (!v) return;
                    setPageSize(Number(v));
                    setPageIndex(0);
                  }}
                  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={clampedIndex === 0}
                  onClick={() => goToPage(clampedIndex - 1)}
                  ariaLabel="Previous page"
                />
                {pageNumbers(clampedIndex, pageCount).map((p, i) =>
                  p === "…" ? (
                    <Text key={`gap-${i}`} fz={13} c="dimmed" px={4}>
                      …
                    </Text>
                  ) : (
                    <PageChip
                      key={p}
                      page={p}
                      active={p === clampedIndex}
                      onClick={() => goToPage(p)}
                    />
                  ),
                )}
                <PagerButton
                  icon={<ChevronRight size={16} />}
                  disabled={clampedIndex >= pageCount - 1}
                  onClick={() => goToPage(clampedIndex + 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>
  );
}
