import {
  ActionIcon,
  Alert,
  Anchor,
  Badge,
  Box,
  Button,
  Card,
  Center,
  Container,
  Divider,
  Group,
  Loader,
  SimpleGrid,
  Stack,
  Tabs,
  Text,
} from "@mantine/core";
import {
  ArrowLeft,
  ArrowRight,
  Banknote,
  Download,
  Eye,
  FileText,
  Hourglass,
  IdCard,
  LayoutGrid,
  Package,
  FilePen,
  Paperclip,
  Receipt,
} from "lucide-react";
import { useQuery } from "@tanstack/react-query";
import { useMemo, useState } from "react";
import { useNavigate, useParams } from "react-router-dom";

import {
  BookingStatusBadge,
  ChangeRequestPendingBadge,
  ChangeRequestReview,
  CompanyStatusBadge,
  CompanyTypeBadge,
  InvoiceStatusBadge,
  PaymentStatusBadge,
  ProfileApprovalActions,
  ProfileChips,
  ProfileStatusBadge,
  ProfileTypeBadge,
  RequestDocumentChangeModal,
  ResetPasswordAction,
  TableCard,
  formatBytes,
  formatDate,
  formatMoney,
  humanize,
} from "@/components/customers";
import { KpiStrip, PageContainer, PageHeader } from "@/components/page";
import { useAuth } from "@/auth/useAuth";
import { FREIGHT_PERMS, hasPermission } from "@/lib/permissions";
import {
  downloadBookingFile,
  fetchViewableFile,
} from "@/services/files.service";
import { api } from "@/services/api";
import type {
  CompanyProfile,
  CustomerBooking,
  CustomerDocument,
  CustomerPayment,
} from "@/types/customer";
import { hasSubmittedOnboarding, isOnboardingDraft } from "@/types/customer";
import type { Invoice } from "@/types/invoice";
import {
  DataTable,
  useFileViewer,
  usePagination,
  type ColumnDef,
} from "@edr/ui-common";

function InfoField({ label, value }: { label: string; value?: string | null }) {
  return (
    <Stack gap={2}>
      <Text
        size="xs"
        fw={600}
        c="edr-muted"
        tt="uppercase"
        style={{ letterSpacing: "0.04em" }}
      >
        {label}
      </Text>
      <Text size="sm" c="edr-text">
        {value && value.trim() ? value : "—"}
      </Text>
    </Stack>
  );
}

function tableStatus(query: { isLoading: boolean; isError: boolean }) {
  return query.isLoading ? "loading" : query.isError ? "error" : "success";
}

/** Matches the fileKey seeded in the API's file-upload-settings seeder. */
const POA_DELEGATION_CODE = "poa_delegation_letter";
/** A letter uploaded by an approved customer, awaiting this reviewer's approval. */
const POA_DELEGATION_PENDING_CODE = "poa_delegation_letter_pending";

export default function CustomerDetailPage() {
  const { id } = useParams<{ id: string }>();
  const navigate = useNavigate();
  const { view, viewer } = useFileViewer();
  const { user } = useAuth();

  const { data: company, isLoading } = useQuery(
    api.customers.getById.queryOptions({
      input: { id: id ?? "" },
      enabled: Boolean(id),
    }),
  );
  const bookingsQuery = useQuery(
    api.customers.bookings.queryOptions({
      input: { id: id ?? "" },
      enabled: Boolean(id),
    }),
  );
  const documentsQuery = useQuery(
    api.customers.documents.queryOptions({
      input: { id: id ?? "" },
      enabled: Boolean(id),
    }),
  );
  const paymentsQuery = useQuery(
    api.customers.payments.queryOptions({
      input: { id: id ?? "" },
      enabled: Boolean(id),
    }),
  );

  const { pagination: invoicePagination, setPagination: setInvoicePagination } =
    usePagination({
      pageSize: 10,
    });
  const invoiceFilter = useMemo(
    () => ({
      companyId: id ?? "",
      page: invoicePagination.pageIndex + 1,
      pageSize: invoicePagination.pageSize,
    }),
    [id, invoicePagination.pageIndex, invoicePagination.pageSize],
  );
  const invoicesQuery = useQuery(
    api.invoices.list.queryOptions({
      input: { filter: invoiceFilter },
      enabled: Boolean(id),
    }),
  );

  const bookings = Array.isArray(bookingsQuery.data) ? bookingsQuery.data : [];
  const documents = Array.isArray(documentsQuery.data)
    ? documentsQuery.data
    : [];
  const payments = Array.isArray(paymentsQuery.data) ? paymentsQuery.data : [];
  const invoices = invoicesQuery.data?.items ?? [];
  const invoiceTotal = invoicesQuery.data?.total ?? 0;
  const invoicePageCount = Math.max(
    1,
    Math.ceil(invoiceTotal / invoicePagination.pageSize),
  );

  const totalPaid = useMemo(
    () =>
      payments
        .filter((p) => p.status === "success")
        .reduce((sum, p) => sum + p.amount, 0),
    [payments],
  );
  const paidCurrency = payments[0]?.currency ?? "ETB";

  // The company row is created on the wizard's first click, so a draft reaches
  // this page with a placeholder name/TIN. `stillOnboarding` drives the banner
  // and badge; `canReview` gates the approve/reject buttons and mirrors the
  // API's rule exactly, so no button is offered that the server would reject.
  const stillOnboarding = company ? isOnboardingDraft(company) : false;
  const canReview = company ? hasSubmittedOnboarding(company) : true;
  // Workflow gate (above) AND authority: asking the customer to correct a
  // document is a `customers:verify` action, so a view-only reviewer reads the
  // documents but is not offered the request-change control.
  const canRequestDocChange =
    canReview && hasPermission(user, FREIGHT_PERMS.customers.verify);

  /** Document the reviewer is asking the customer to correct; null = closed. */
  const [changeRequestDoc, setChangeRequestDoc] =
    useState<CustomerDocument | null>(null);

  const profileColumns: ColumnDef<CompanyProfile>[] = useMemo(
    () => [
      {
        id: "type",
        header: "Role",
        cell: ({ row }) => (
          <div className="space-y-2">
            <ProfileTypeBadge type={row.original.type} />

            <Text size="sm" fw={600} c="edr-text">
              {row.original.reference}
            </Text>
          </div>
        ),
      },
      {
        id: "licenseFiles",
        header: "License documents",
        cell: ({ row }) => {
          const files = row.original.licenseFiles ?? [];
          if (files.length === 0) {
            return (
              <Text size="sm" c="dimmed">
                —
              </Text>
            );
          }
          return (
            <Stack gap={4}>
              {files.map((f) => (
                <Group key={f.id} gap={6} wrap="nowrap">
                  <ActionIcon
                    size="sm"
                    variant="subtle"
                    color="gray"
                    aria-label={`View ${f.name}`}
                    onClick={() => void fetchViewableFile(f.id, f.name).then(view)}
                  >
                    <Eye size={14} />
                  </ActionIcon>
                  <Anchor
                    component="button"
                    type="button"
                    size="xs"
                    lineClamp={1}
                    onClick={() => void fetchViewableFile(f.id, f.name).then(view)}
                    style={{
                      maxWidth: 170,
                      textAlign: "left",
                      textDecoration:
                        f.status === "pending_remove"
                          ? "line-through"
                          : undefined,
                    }}
                  >
                    {f.name}
                  </Anchor>
                  {f.status === "pending_add" && (
                    <Badge size="xs" color="yellow" variant="light">
                      Pending
                    </Badge>
                  )}
                  {f.status === "pending_remove" && (
                    <Badge size="xs" color="red" variant="light">
                      Removing
                    </Badge>
                  )}
                </Group>
              ))}
            </Stack>
          );
        },
      },
      {
        id: "status",
        header: "Status",
        cell: ({ row }) => <ProfileStatusBadge status={row.original.status} />,
      },
      {
        id: "createdAt",
        header: "Registered",
        cell: ({ row }) => (
          <Text size="sm" c="dimmed">
            {formatDate(row.original.createdAt)}
          </Text>
        ),
      },
      {
        id: "actions",
        header: "",
        meta: { headerClassName: "text-right", cellClassName: "text-right" },
        cell: ({ row }) => (
          <ProfileApprovalActions
            profileId={row.original.id}
            status={row.original.status}
            locked={!canReview}
          />
        ),
      },
    ],
    [view, canReview],
  );

  const bookingColumns: ColumnDef<CustomerBooking>[] = useMemo(
    () => [
      {
        id: "reference",
        header: "Booking",
        cell: ({ row }) => (
          <Text size="sm" fw={600} c="edr-text">
            {row.original.reference}
          </Text>
        ),
      },
      {
        id: "route",
        header: "Route",
        cell: ({ row }) => {
          const b = row.original;
          return (
            <Group gap={6} wrap="nowrap">
              <Text size="sm" c="edr-text">
                {b.originLabel}
              </Text>
              <ArrowRight size={14} className="shrink-0 text-edr-muted" />
              <Text size="sm" c="edr-text">
                {b.destinationLabel}
              </Text>
            </Group>
          );
        },
      },
      {
        id: "type",
        header: "Type",
        cell: ({ row }) => (
          <Text size="sm" c="dimmed">
            {humanize(row.original.tradeDirection)} ·{" "}
            {humanize(row.original.freightType)}
          </Text>
        ),
      },
      {
        id: "status",
        header: "Status",
        cell: ({ row }) => <BookingStatusBadge status={row.original.status} />,
      },
      {
        id: "amount",
        header: "Amount",
        meta: { headerClassName: "text-right", cellClassName: "text-right" },
        cell: ({ row }) => (
          <Text size="sm" fw={600} c="edr-text">
            {formatMoney(row.original.totalAmount, row.original.currency)}
          </Text>
        ),
      },
      {
        id: "createdAt",
        header: "Created",
        meta: { headerClassName: "text-right", cellClassName: "text-right" },
        cell: ({ row }) => (
          <Text size="sm" c="dimmed">
            {formatDate(row.original.createdAt)}
          </Text>
        ),
      },
    ],
    [],
  );

  const documentColumns: ColumnDef<CustomerDocument>[] = useMemo(
    () => [
      {
        id: "name",
        header: "Document",
        cell: ({ row }) => {
          const doc = row.original;
          return (
            <Stack gap={2}>
              <Group gap="sm" wrap="nowrap">
                <FileText size={16} className="shrink-0 text-edr-muted" />
                <Text size="sm" c="edr-text" truncate>
                  {doc.name}
                </Text>
                {doc.reviewStatus === "change_requested" && (
                  <Badge size="xs" color="orange" variant="light">
                    Change requested
                  </Badge>
                )}
              </Group>
              {/* The note is the whole point of the request — show it inline so a
                  second reviewer sees what was already asked for. */}
              {doc.reviewStatus === "change_requested" && doc.reviewNote && (
                <Text size="xs" c="dimmed" pl={24}>
                  {doc.reviewNote}
                </Text>
              )}
            </Stack>
          );
        },
      },
      {
        id: "code",
        header: "Type",
        cell: ({ row }) => (
          <Text size="sm" c="dimmed">
            {humanize(row.original.code)}
          </Text>
        ),
      },
      {
        id: "size",
        header: "Size",
        cell: ({ row }) => (
          <Text size="sm" c="dimmed">
            {formatBytes(row.original.size)}
          </Text>
        ),
      },
      {
        id: "uploadedAt",
        header: "Uploaded",
        cell: ({ row }) => (
          <Text size="sm" c="dimmed">
            {formatDate(row.original.uploadedAt)}
          </Text>
        ),
      },
      {
        id: "actions",
        header: "",
        meta: { headerClassName: "text-right", cellClassName: "text-right" },
        cell: ({ row }) => (
          <Group gap={4} justify="flex-end" wrap="nowrap">
            <ActionIcon
              variant="subtle"
              color="gray"
              aria-label="View"
              data-stop-row-click
              onClick={() =>
                void fetchViewableFile(row.original.id, row.original.name).then(
                  view,
                )
              }
            >
              <Eye size={16} />
            </ActionIcon>
            <ActionIcon
              component="button"
              type="button"
              onClick={() =>
                void downloadBookingFile(row.original.id, row.original.name)
              }
              variant="subtle"
              color="gray"
              aria-label="Download"
              data-stop-row-click
            >
              <Download size={16} />
            </ActionIcon>
            {canRequestDocChange && (
              <ActionIcon
                component="button"
                type="button"
                variant="subtle"
                color="orange"
                aria-label="Request change"
                title={
                  row.original.reviewStatus === "change_requested"
                    ? "Update the requested change"
                    : "Request a change from the customer"
                }
                data-stop-row-click
                onClick={() => setChangeRequestDoc(row.original)}
              >
                <FilePen size={16} />
              </ActionIcon>
            )}
          </Group>
        ),
      },
    ],
    [view, canRequestDocChange],
  );

  const paymentColumns: ColumnDef<CustomerPayment>[] = useMemo(
    () => [
      {
        id: "reference",
        header: "Payment",
        cell: ({ row }) => (
          <Text size="sm" fw={600} c="edr-text">
            {row.original.reference}
          </Text>
        ),
      },
      {
        id: "booking",
        header: "Booking",
        cell: ({ row }) => (
          <Text size="sm" c="dimmed">
            {row.original.bookingReference}
          </Text>
        ),
      },
      {
        id: "method",
        header: "Method",
        cell: ({ row }) => (
          <Text size="sm" c="dimmed">
            {humanize(row.original.method)}
          </Text>
        ),
      },
      {
        id: "status",
        header: "Status",
        cell: ({ row }) => <PaymentStatusBadge status={row.original.status} />,
      },
      {
        id: "paidAt",
        header: "Paid",
        cell: ({ row }) => (
          <Text size="sm" c="dimmed">
            {formatDate(row.original.paidAt)}
          </Text>
        ),
      },
      {
        id: "amount",
        header: "Amount",
        meta: { headerClassName: "text-right", cellClassName: "text-right" },
        cell: ({ row }) => (
          <Text size="sm" fw={600} c="edr-text">
            {formatMoney(row.original.amount, row.original.currency)}
          </Text>
        ),
      },
    ],
    [],
  );

  const invoiceColumns: ColumnDef<Invoice>[] = useMemo(
    () => [
      {
        id: "invoiceNumber",
        header: "Invoice",
        cell: ({ row }) => (
          <Text size="sm" fw={600} c="edr-text">
            {row.original.invoiceNumber}
          </Text>
        ),
      },
      {
        id: "source",
        header: "Source",
        cell: ({ row }) => (
          <Text size="sm" c="dimmed">
            {humanize(row.original.source)}
          </Text>
        ),
      },
      {
        id: "status",
        header: "Status",
        cell: ({ row }) => <InvoiceStatusBadge status={row.original.status} />,
      },
      {
        id: "amount",
        header: "Amount",
        meta: { headerClassName: "text-right", cellClassName: "text-right" },
        cell: ({ row }) => (
          <Text size="sm" fw={600} c="edr-text">
            {formatMoney(row.original.totalAmount, row.original.currency)}
          </Text>
        ),
      },
      {
        id: "dueAt",
        header: "Due",
        meta: { headerClassName: "text-right", cellClassName: "text-right" },
        cell: ({ row }) => (
          <Text size="sm" c="dimmed">
            {formatDate(row.original.dueAt)}
          </Text>
        ),
      },
    ],
    [],
  );

  const licenseProfiles = (company?.companyProfiles ?? []).filter(
    (p) => p.licenseFiles && p.licenseFiles.length > 0,
  );

  const poaDocuments = useMemo(
    () =>
      documents.filter(
        (d) =>
          d.code === POA_DELEGATION_CODE ||
          d.code === POA_DELEGATION_PENDING_CODE,
      ),
    [documents],
  );
  const poaLive = poaDocuments.filter((d) => d.code === POA_DELEGATION_CODE);
  const poaFields = [
    { label: "PoA name", value: company?.poaName },
    { label: "PoA email", value: company?.poaEmail },
    { label: "PoA phone", value: company?.poaPhone },
    { label: "PoA location", value: company?.poaLocation },
    { label: "PoA address", value: company?.poaAddress },
  ];
  const hasPoaDetails = poaFields.some((f) => f.value?.trim());
  // A freight forwarder acts on other companies' behalf, so its PoA — details
  // and delegation letter both — is mandatory rather than optional.
  const poaMandatory = (company?.companyProfiles ?? []).some(
    (p) => p.type === "freight_forwarder",
  );
  const delegationMissing =
    (hasPoaDetails || poaMandatory) && poaLive.length === 0;

  if (isLoading) {
    return (
      <Center mih="60vh">
        <Loader />
      </Center>
    );
  }

  if (!company) {
    return (
      <Container size="sm" py="xl">
        <Stack align="center" gap="md">
          <Text fw={700}>Customer not found</Text>
          <Button
            variant="default"
            leftSection={<ArrowLeft size={16} />}
            onClick={() => navigate("/dashboard/customers")}
          >
            Back to customers
          </Button>
        </Stack>
      </Container>
    );
  }

  return (
    <PageContainer>
      <PageHeader
        breadcrumbs={[
          { label: "Customers", href: "/dashboard/customers" },
          { label: company.name },
        ]}
        backTo="/dashboard/customers"
        title={company.name}
        subtitle={`TIN ${company.tin}${company.country ? ` · ${company.country}` : ""
          }`}
        meta={
          <Group gap="xs" wrap="nowrap">
            <CompanyTypeBadge type={company.type} />
            {stillOnboarding ? (
              <Badge color="gray" variant="light" size="sm" radius="sm">
                Onboarding in progress
              </Badge>
            ) : (
              <CompanyStatusBadge status={company.status} />
            )}
            <ChangeRequestPendingBadge companyId={company.id} />
          </Group>
        }
        action={<ResetPasswordAction company={company} />}
      />

      <Tabs defaultValue="overview">
        <Tabs.List>
          <Tabs.Tab value="overview" leftSection={<LayoutGrid size={16} />}>
            Overview
          </Tabs.Tab>
          <Tabs.Tab value="bookings" leftSection={<Package size={16} />}>
            Bookings
          </Tabs.Tab>
          <Tabs.Tab value="documents" leftSection={<FileText size={16} />}>
            Documents
          </Tabs.Tab>
          <Tabs.Tab value="payments" leftSection={<Banknote size={16} />}>
            Payments
          </Tabs.Tab>
          <Tabs.Tab value="invoices" leftSection={<Receipt size={16} />}>
            Invoices
          </Tabs.Tab>
        </Tabs.List>

        {/* OVERVIEW */}
        <Tabs.Panel value="overview" pt="lg">
          <Stack gap="lg">
            {stillOnboarding && (
              <Alert
                color="gray"
                variant="light"
                radius="md"
                icon={<Hourglass size={18} />}
                title="This customer hasn't submitted their application yet"
              >
                They're still filling in the onboarding wizard, so the details
                below are an unfinished draft — the company name and TIN are
                placeholders until they reach those steps. Role profiles become
                reviewable once the application is submitted.
              </Alert>
            )}

            <ChangeRequestReview company={company} />

            <KpiStrip
              items={[
                {
                  label: "Profiles",
                  value: company.companyProfiles.length,
                  icon: IdCard,
                  color: "edr-green",
                },
                {
                  // A draft's profiles are all `pending` by construction, which
                  // would read as a review backlog that doesn't exist yet.
                  label: stillOnboarding
                    ? "Awaiting submission"
                    : "Pending approval",
                  value: stillOnboarding
                    ? "—"
                    : company.companyProfiles.filter(
                        (p) => p.status === "pending",
                      ).length,
                  icon: IdCard,
                  color: "yellow",
                },
                {
                  label: "Bookings",
                  value: bookings.length,
                  icon: Package,
                  color: "blue",
                },
                {
                  label: "Total paid",
                  value: formatMoney(totalPaid, paidCurrency),
                  icon: Banknote,
                  color: "edr-green",
                },
              ]}
            />

            <Card>
              <Stack gap="lg">
                <Text fw={600} c="edr-text">
                  Company information
                </Text>
                <SimpleGrid cols={{ base: 1, sm: 2, lg: 3 }} spacing="lg">
                  <InfoField label="TIN" value={company.tin} />
                  <InfoField label="VAT number" value={company.vatNumber} />
                  <InfoField label="FAN number" value={company.fanNumber} />
                  <InfoField label="Country" value={company.country} />
                  <InfoField label="Address" value={company.address} />
                  <InfoField label="Website" value={company.website} />
                  <InfoField label="Email" value={company.email} />
                  <InfoField label="Phone" value={company.phone} />
                  <Box />
                  <InfoField
                    label="Contact person"
                    value={company.contactPersonName}
                  />
                  <InfoField
                    label="Contact phone"
                    value={company.contactPersonPhone}
                  />
                  <Box />
                  <InfoField
                    label="General manager"
                    value={company.generalManagerName}
                  />
                  <InfoField
                    label="GM email"
                    value={company.generalManagerEmail}
                  />
                  <InfoField
                    label="GM phone"
                    value={company.generalManagerPhone}
                  />
                </SimpleGrid>
              </Stack>
            </Card>

            <Card>
              <Stack gap="lg">
                <Group justify="space-between" wrap="nowrap">
                  <Group gap="xs" wrap="nowrap">
                    <Text fw={600} c="edr-text">
                      Power of Attorney
                    </Text>
                    {poaMandatory && (
                      <Badge size="xs" color="blue" variant="light">
                        Required for freight forwarder
                      </Badge>
                    )}
                  </Group>
                  {delegationMissing ? (
                    <Badge size="sm" color="red" variant="light">
                      Delegation letter missing
                    </Badge>
                  ) : poaLive.length > 0 ? (
                    <Badge size="sm" color="edr-green" variant="light">
                      Delegation letter on file
                    </Badge>
                  ) : (
                    <Badge size="sm" color="gray" variant="light">
                      Not provided
                    </Badge>
                  )}
                </Group>

                {hasPoaDetails ? (
                  <SimpleGrid cols={{ base: 1, sm: 2, lg: 3 }} spacing="lg">
                    {poaFields.map((f) => (
                      <InfoField
                        key={f.label}
                        label={f.label}
                        value={f.value}
                      />
                    ))}
                  </SimpleGrid>
                ) : (
                  <Text size="sm" c="dimmed">
                    No Power of Attorney representative recorded for this
                    customer.
                  </Text>
                )}

                <Divider />

                <Stack gap="sm">
                  <Text
                    size="xs"
                    fw={600}
                    c="edr-muted"
                    tt="uppercase"
                    style={{ letterSpacing: "0.04em" }}
                  >
                    Delegation letter
                  </Text>

                  {documentsQuery.isLoading ? (
                    <Group gap="xs">
                      <Loader size="xs" />
                      <Text size="sm" c="dimmed">
                        Loading documents…
                      </Text>
                    </Group>
                  ) : documentsQuery.isError ? (
                    <Group gap="sm">
                      <Text size="sm" c="red">
                        Failed to load documents.
                      </Text>
                      <Anchor
                        component="button"
                        type="button"
                        size="xs"
                        onClick={() => void documentsQuery.refetch()}
                      >
                        Retry
                      </Anchor>
                    </Group>
                  ) : poaDocuments.length === 0 ? (
                    <Text size="sm" c="dimmed">
                      No delegation letter uploaded.
                    </Text>
                  ) : (
                    poaDocuments.map((doc) => (
                      <Group key={doc.id} justify="space-between" wrap="nowrap">
                        <Group gap="sm" wrap="nowrap" style={{ minWidth: 0 }}>
                          <Paperclip
                            size={14}
                            className="shrink-0 text-edr-muted"
                          />
                          <Anchor
                            component="button"
                            type="button"
                            size="sm"
                            lineClamp={1}
                            onClick={() =>
                              void fetchViewableFile(doc.id, doc.name).then(view)
                            }
                          >
                            {doc.name}
                          </Anchor>
                          <Text size="xs" c="dimmed" className="shrink-0">
                            {formatBytes(doc.size)} ·{" "}
                            {formatDate(doc.uploadedAt)}
                          </Text>
                          {doc.code === POA_DELEGATION_PENDING_CODE && (
                            <Badge
                              size="xs"
                              color="yellow"
                              variant="light"
                              className="shrink-0"
                            >
                              Pending approval
                            </Badge>
                          )}
                        </Group>
                        <Group gap={4} wrap="nowrap">
                          <ActionIcon
                            variant="subtle"
                            color="gray"
                            aria-label={`Preview ${doc.name}`}
                            onClick={() =>
                              void fetchViewableFile(doc.id, doc.name).then(view)
                            }
                          >
                            <Eye size={16} />
                          </ActionIcon>
                          <ActionIcon
                            component="button"
                            type="button"
                            onClick={() =>
                              void downloadBookingFile(doc.id, doc.name)
                            }
                            variant="subtle"
                            color="gray"
                            aria-label={`Download ${doc.name}`}
                          >
                            <Download size={16} />
                          </ActionIcon>
                        </Group>
                      </Group>
                    ))
                  )}
                </Stack>
              </Stack>
            </Card>

            <Card>
              <Stack gap="md">
                <Group justify="space-between">
                  <Text fw={600} c="edr-text">
                    Role profiles
                  </Text>
                  <ProfileChips profiles={company.companyProfiles} />
                </Group>
                <Box style={{ overflowX: "auto" }} w="100%">
                  <Box miw={1040}>
                    <DataTable
                      columns={profileColumns}
                      data={company.companyProfiles}
                      status="success"
                      emptyMessage="No profiles registered."
                      containerClassName="border-0 shadow-none bg-transparent"
                    />
                  </Box>
                </Box>
              </Stack>
            </Card>
          </Stack>
        </Tabs.Panel>

        {/* BOOKINGS */}
        <Tabs.Panel value="bookings" pt="lg">
          <TableCard minWidth={900}>
            <DataTable
              columns={bookingColumns}
              data={bookings}
              status={tableStatus(bookingsQuery)}
              emptyMessage="No bookings for this customer."
              containerClassName="border-0 shadow-none bg-transparent"
              error={
                bookingsQuery.isError
                  ? {
                    message: "Failed to load bookings.",
                    onRetry: () => void bookingsQuery.refetch(),
                  }
                  : undefined
              }
            />
          </TableCard>
        </Tabs.Panel>

        {/* DOCUMENTS */}
        <Tabs.Panel value="documents" pt="lg">
          <Stack gap="lg">
            <TableCard minWidth={760}>
              <DataTable
                columns={documentColumns}
                data={documents}
                status={tableStatus(documentsQuery)}
                emptyMessage="No documents uploaded."
                containerClassName="border-0 shadow-none bg-transparent"
                error={
                  documentsQuery.isError
                    ? {
                      message: "Failed to load documents.",
                      onRetry: () => void documentsQuery.refetch(),
                    }
                    : undefined
                }
              />
            </TableCard>

            {licenseProfiles.length > 0 && (
              <Card>
                <Stack gap="md">
                  <Text fw={600} c="edr-text">
                    Business licenses
                  </Text>
                  <Stack gap="md">
                    {licenseProfiles.map((p) => (
                      <Stack key={p.id} gap={6}>
                        <Text size="sm" fw={600} c="edr-text">
                          {humanize(p.type)} · {p.reference}
                        </Text>
                        {(p.licenseFiles ?? []).map((f) => (
                          <Group key={f.id} gap={8} wrap="nowrap">
                            <Paperclip size={13} className="text-edr-muted" />
                            <Anchor
                              component="button"
                              type="button"
                              onClick={() =>
                                void fetchViewableFile(f.id, f.name).then(view)
                              }
                              size="xs"
                              style={{
                                textDecoration:
                                  f.status === "pending_remove"
                                    ? "line-through"
                                    : undefined,
                              }}
                            >
                              {f.name}
                            </Anchor>
                            {f.status === "pending_add" && (
                              <Badge size="xs" color="yellow" variant="light">
                                Pending approval
                              </Badge>
                            )}
                            {f.status === "pending_remove" && (
                              <Badge size="xs" color="red" variant="light">
                                Removal pending
                              </Badge>
                            )}
                          </Group>
                        ))}
                        {(p.licenseFiles ?? []).length === 0 && (
                          <Text size="xs" c="dimmed">
                            No license documents.
                          </Text>
                        )}
                      </Stack>
                    ))}
                  </Stack>
                </Stack>
              </Card>
            )}
          </Stack>
        </Tabs.Panel>

        {/* PAYMENTS */}
        <Tabs.Panel value="payments" pt="lg">
          <TableCard minWidth={880}>
            <DataTable
              columns={paymentColumns}
              data={payments}
              status={tableStatus(paymentsQuery)}
              emptyMessage="No payments recorded."
              containerClassName="border-0 shadow-none bg-transparent"
              error={
                paymentsQuery.isError
                  ? {
                    message: "Failed to load payments.",
                    onRetry: () => void paymentsQuery.refetch(),
                  }
                  : undefined
              }
            />
          </TableCard>
        </Tabs.Panel>

        {/* INVOICES */}
        <Tabs.Panel value="invoices" pt="lg">
          <Box style={{ overflowX: "auto" }} w="100%">
            <Box miw={860}>
              <DataTable
                columns={invoiceColumns}
                data={invoices}
                status={tableStatus(invoicesQuery)}
                onRowClick={(row) => navigate(`/dashboard/invoices/${row.id}`)}
                emptyMessage="No invoices for this customer."
                containerClassName="border-0 shadow-none bg-transparent"
                error={
                  invoicesQuery.isError
                    ? {
                      message: "Failed to load invoices.",
                      onRetry: () => void invoicesQuery.refetch(),
                    }
                    : undefined
                }
                pagination={{
                  pageIndex: invoicePagination.pageIndex,
                  pageSize: invoicePagination.pageSize,
                  pageCount: invoicePageCount,
                  totalCount: invoiceTotal,
                }}
                tableOptions={{
                  state: { pagination: invoicePagination },
                  onPaginationChange: setInvoicePagination,
                  manualPagination: true,
                  pageCount: invoicePageCount,
                }}
              />
            </Box>
          </Box>
        </Tabs.Panel>
      </Tabs>

      <RequestDocumentChangeModal
        document={changeRequestDoc}
        companyId={company.id}
        onClose={() => setChangeRequestDoc(null)}
      />

      {viewer}
    </PageContainer>
  );
}
