import {
  ActionIcon,
  Badge,
  Box,
  Card,
  Group,
  SegmentedControl,
  Select,
  Stack,
  Text,
  TextInput,
  Tooltip,
} from "@mantine/core";
import { useDebouncedValue } from "@mantine/hooks";
import { useQuery } from "@tanstack/react-query";
import {
  Building2,
  CheckCircle2,
  Clock,
  FilePen,
  Hourglass,
  Mail,
  Phone,
  RefreshCw,
  Search,
  ShieldOff,
  Users,
  X,
} from "lucide-react";
import { useMemo, useState } from "react";
import { useNavigate } from "react-router-dom";

import {
  CompanyStatusBadge,
  ProfileChips,
  formatDate,
} from "@/components/customers";
import { KpiStrip, PageContainer, PageHeader } from "@/components/page";
import { api } from "@/services/api";
import type { Company, CompanyStatus } from "@/types/customer";
import { isOnboardingDraft } from "@/types/customer";
import {
  DataTable,
  DataTableFooter,
  usePagination,
  type ColumnDef,
} from "@edr/ui-common";

/**
 * The list's segmented views. "Pending approval" means submitted-and-awaiting-
 * review, so it excludes drafts — a company row exists from the onboarding
 * wizard's first click and would otherwise pad the review queue. Those drafts
 * get their own view instead of disappearing, so staff can still chase them.
 */
type CustomerView =
  | "all"
  | "pending"
  | "pendingChanges"
  | "onboarding"
  | "active";

/**
 * "Pending changes" is deliberately not folded into "Pending approval". A
 * customer who edits their profile after being approved stays `status = active`,
 * so the pending filter can never match them — their resubmission would only
 * ever be visible by opening their detail page. This view is that queue.
 */
const VIEW_FILTERS: Record<
  CustomerView,
  {
    status?: CompanyStatus;
    onboardingCompleted?: boolean;
    hasPendingChangeRequest?: boolean;
  }
> = {
  all: {},
  pending: { status: "pending", onboardingCompleted: true },
  pendingChanges: { hasPendingChangeRequest: true },
  onboarding: { onboardingCompleted: false },
  active: { status: "active" },
};

const SORT_OPTIONS = [
  // Queue ordering: awaiting first approval → pending profile changes → the
  // rest, newest first within each group. The default, so whatever marketing
  // must act on is always on top of the list.
  { value: "review:DESC", label: "Needs review first" },
  { value: "createdAt:DESC", label: "Newest first" },
  { value: "createdAt:ASC", label: "Oldest first" },
  { value: "name:ASC", label: "Name (A–Z)" },
  { value: "name:DESC", label: "Name (Z–A)" },
] as const;

export default function CustomersPage() {
  const navigate = useNavigate();
  const { pagination, setPagination } = usePagination({ pageSize: 10 });
  const [query, setQuery] = useState("");
  const [debouncedQuery] = useDebouncedValue(query, 300);
  const [view, setView] = useState<CustomerView>("all");
  const [sort, setSort] = useState<string>("review:DESC");

  const filter = useMemo(() => {
    const [sortBy, sortOrder] = sort.split(":") as [
      "review" | "name" | "createdAt" | "updatedAt",
      "ASC" | "DESC",
    ];
    return {
      page: pagination.pageIndex + 1,
      pageSize: pagination.pageSize,
      search: debouncedQuery,
      sortBy,
      sortOrder,
      ...VIEW_FILTERS[view],
    };
  }, [pagination.pageIndex, pagination.pageSize, debouncedQuery, view, sort]);

  const { data: stats } = useQuery(
    api.customers.stats.queryOptions({ input: {} }),
  );

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

  const rows = data?.items ?? [];
  const total = data?.total ?? 0;
  const pageCount = Math.max(1, Math.ceil(total / pagination.pageSize));

  const columns: ColumnDef<Company>[] = useMemo(
    () => [
      {
        id: "company",
        header: "Company",
        cell: ({ row }) => {
          const c = row.original;
          return (
            <Group gap="sm" wrap="nowrap">
              <Box
                className="flex size-9 shrink-0 items-center justify-center rounded-lg"
                style={{
                  background: "var(--mantine-color-edr-green-1)",
                  color: "var(--mantine-color-edr-green-7)",
                }}
              >
                <Building2 size={18} strokeWidth={1.9} />
              </Box>
              <div style={{ minWidth: 0 }}>
                <Group gap={8} wrap="nowrap">
                  <Text fw={600} c="edr-text" truncate>
                    {c.name}
                  </Text>
                </Group>
                <Text size="xs" c="dimmed">
                  TIN {c.tin}
                  {c.country ? ` · ${c.country}` : ""}
                </Text>
              </div>
            </Group>
          );
        },
      },
      {
        id: "profiles",
        header: "Profiles",
        cell: ({ row }) => (
          <ProfileChips profiles={row.original.companyProfiles} />
        ),
      },
      {
        id: "status",
        header: "Status",
        cell: ({ row }) => {
          // A draft's profiles are all `pending` by construction, so the
          // "N pending" review hint would be a lie until they submit.
          if (isOnboardingDraft(row.original)) {
            return (
              <Tooltip label="Customer is still filling in the onboarding wizard">
                <Badge color="gray" variant="light" size="sm" radius="sm">
                  Onboarding
                </Badge>
              </Tooltip>
            );
          }
          const pending = (row.original.companyProfiles ?? []).filter(
            (p) => p.status === "pending",
          ).length;
          return (
            <Group gap={6} wrap="nowrap">
              <CompanyStatusBadge status={row.original.status} />
              {pending > 0 ? (
                <Tooltip
                  label={`${pending} profile${pending > 1 ? "s" : ""} awaiting approval`}
                >
                  <Badge color="yellow" variant="light" size="sm" radius="sm">
                    {pending} pending
                  </Badge>
                </Tooltip>
              ) : null}
            </Group>
          );
        },
      },
      {
        id: "contact",
        header: "Contact",
        cell: ({ row }) => {
          const c = row.original;
          return (
            <Stack gap={2}>
              {c.contactPersonName ? (
                <Text size="sm" c="edr-text">
                  {c.contactPersonName}
                </Text>
              ) : null}
              {c.phone ? (
                <Text
                  size="xs"
                  c="dimmed"
                  className="inline-flex items-center gap-1"
                >
                  <Phone size={12} /> {c.phone}
                </Text>
              ) : null}
              {c.email ? (
                <Text
                  size="xs"
                  c="dimmed"
                  className="inline-flex items-center gap-1"
                  truncate
                >
                  <Mail size={12} /> {c.email}
                </Text>
              ) : null}
            </Stack>
          );
        },
      },
      {
        id: "created",
        header: "Registered",
        meta: { headerClassName: "text-right", cellClassName: "text-right" },
        cell: ({ row }) => (
          <Text size="sm" c="dimmed">
            {formatDate(row.original.createdAt)}
          </Text>
        ),
      },
    ],
    [],
  );

  return (
    <PageContainer>
      <PageHeader
        title="Customers"
        subtitle="Companies registered for freight services, with their role profiles."
        action={
          <ActionIcon
            variant="default"
            size="lg"
            radius="md"
            aria-label="Refresh"
            loading={isFetching}
            onClick={() => void refetch()}
          >
            <RefreshCw size={16} />
          </ActionIcon>
        }
      />

      <KpiStrip
        items={[
          {
            label: "Companies",
            value: stats?.total ?? "—",
            icon: Users,
            color: "edr-green",
          },
          {
            label: "Active",
            value: stats?.active ?? "—",
            icon: CheckCircle2,
            color: "edr-green",
          },
          {
            label: "Pending",
            value: stats?.pending ?? "—",
            icon: Clock,
            color: "yellow",
          },
          {
            label: "Pending changes",
            value: stats?.pendingChanges ?? "—",
            icon: FilePen,
            color: "yellow",
          },
          {
            label: "Onboarding",
            value: stats?.onboarding ?? "—",
            icon: Hourglass,
            color: "gray",
          },
          {
            label: "Blacklisted",
            value: stats?.blacklisted ?? "—",
            icon: ShieldOff,
            color: "red",
          },
        ]}
      />

      <Card p={0}>
        <Stack gap={0}>
          <Box px="md" pt="md" pb="sm" w="100%">
            <Group justify="space-between" gap="md" wrap="wrap">
              <TextInput
                placeholder="Search by company, TIN, email or profile reference…"
                leftSection={<Search size={18} />}
                value={query}
                onChange={(e) => setQuery(e.target.value)}
                rightSection={
                  query ? (
                    <ActionIcon
                      size="sm"
                      color="gray"
                      radius="md"
                      variant="transparent"
                      onClick={() => setQuery("")}
                    >
                      <X size={16} />
                    </ActionIcon>
                  ) : null
                }
                style={{ flex: 1, minWidth: "240px" }}
                radius="lg"
              />
              <SegmentedControl
                size="sm"
                radius="md"
                value={view}
                onChange={(v) => {
                  setView(v as CustomerView);
                  setPagination((prev) => ({ ...prev, pageIndex: 0 }));
                }}
                data={[
                  { label: "All", value: "all" },
                  { label: "Pending approval", value: "pending" },
                  { label: "Pending changes", value: "pendingChanges" },
                  { label: "Onboarding", value: "onboarding" },
                  { label: "Active", value: "active" },
                ]}
              />
              <Select
                size="sm"
                radius="md"
                w={160}
                allowDeselect={false}
                aria-label="Sort customers"
                value={sort}
                onChange={(v) => {
                  if (!v) return;
                  setSort(v);
                  setPagination((prev) => ({ ...prev, pageIndex: 0 }));
                }}
                data={SORT_OPTIONS.map((o) => ({ ...o }))}
              />
              <Text size="sm" c="dimmed">
                {total} record{total !== 1 ? "s" : ""}
              </Text>
            </Group>
          </Box>

          <Box style={{ overflowX: "auto" }} w="100%">
            <Box miw={980}>
              <DataTable
                columns={columns}
                data={rows}
                status={isLoading ? "loading" : isError ? "error" : "success"}
                onRowClick={(row) => navigate(`/dashboard/customers/${row.id}`)}
                emptyMessage={
                  debouncedQuery
                    ? "No companies match your search."
                    : "No companies yet."
                }
                error={
                  isError
                    ? {
                      message: "Failed to load customers.",
                      onRetry: () => void refetch(),
                    }
                    : undefined
                }
                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>
          </Box>
        </Stack>
      </Card>
    </PageContainer>
  );
}
