"use client";

import * as React from "react";
import { useRouter } from "next/navigation";
import { EyeIcon } from "lucide-react";

import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
import { EmptyState } from "@/components/ui/empty-state";
import { Tabs, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { Typography } from "@/components/ui/typography";
import { DataTable, useDataTableQuery } from "@/components/data-table";
import type { DataTableColumn } from "@/components/data-table";
import { useProviders } from "@/hooks/providers/useProviders";
import { useTranslation } from "@/hooks/useTranslation";
import { ROUTES } from "@/lib/constants/routes";
import { ProviderStatus } from "@/types/provider";
import type { ProviderListItem } from "@/types/provider";

import { ProviderStatusBadge } from "./ProviderStatusBadge";
import { ProviderStatusConfirmDialog } from "./ProviderStatusConfirmDialog";
import { formatDay } from "./lib/format";
import {
  PROVIDER_STATUS_TABS,
  formatCommissionRate,
  getStatusActions,
  type ProviderStatusAction,
} from "./lib/provider-status";

const ALL_TAB = "ALL";
type StatusFilter = ProviderStatus | typeof ALL_TAB;

/**
 * Admin provider list — also the registration-review queue.
 *
 * "Provider Listing" and "Provider Registration Review" are one screen: the
 * status tabs switch between all providers and the pending-review queue, and
 * both drill into the same detail page. They read from the same endpoint, so
 * splitting them would duplicate the table for no behavioral gain.
 *
 * Server mode: the backend owns search/filter/pagination. Columns are NOT
 * marked sortable — `GET /providers/admin` has no sort parameter (it hardcodes
 * `createdAt desc`), and its `forbidNonWhitelisted` validation would 400 on an
 * unexpected query key.
 */
export function ProvidersView() {
  const { t, language } = useTranslation();
  const router = useRouter();

  const { query, setQuery } = useDataTableQuery();
  const [statusFilter, setStatusFilter] = React.useState<StatusFilter>(ALL_TAB);
  const [pendingAction, setPendingAction] =
    React.useState<ProviderStatusAction | null>(null);
  const [actionTarget, setActionTarget] =
    React.useState<ProviderListItem | null>(null);

  const { data, isLoading, isError, refetch } = useProviders({
    search: query.search,
    status: statusFilter === ALL_TAB ? undefined : statusFilter,
    page: query.page,
    limit: query.pageSize,
  });

  function handleStatusFilterChange(next: StatusFilter) {
    setStatusFilter(next);
    // A page-2 view of "all" is meaningless once the filter narrows the set.
    setQuery({ ...query, page: 1 });
  }

  function openStatusAction(
    provider: ProviderListItem,
    action: ProviderStatusAction,
  ) {
    setActionTarget(provider);
    setPendingAction(action);
  }

  const columns = React.useMemo<DataTableColumn<ProviderListItem>[]>(
    () => [
      {
        // First column doubles as the mobile card title — keep it identifying.
        key: "businessName",
        header: t("providers.columns.business"),
        cell: (provider) => (
          <div className="flex min-w-0 items-center gap-2">
            <Avatar>
              {provider.logoUrl && (
                <AvatarImage src={provider.logoUrl} alt="" />
              )}
              <AvatarFallback>
                {provider.businessName.trim().charAt(0).toUpperCase()}
              </AvatarFallback>
            </Avatar>
            <Typography as="span" variant="body" className="truncate">
              {provider.businessName}
            </Typography>
          </div>
        ),
      },
      {
        key: "status",
        header: t("providers.columns.status"),
        cell: (provider) => <ProviderStatusBadge status={provider.status} />,
      },
      {
        key: "rating",
        header: t("providers.columns.rating"),
        cell: (provider) =>
          provider.totalReviews > 0 ? (
            <div className="flex items-center justify-end gap-1 md:justify-start">
              <Typography as="span" variant="number">
                {provider.averageRating.toFixed(1)}
              </Typography>
              <Typography as="span" variant="caption" color="secondary">
                ({provider.totalReviews})
              </Typography>
            </div>
          ) : (
            <Typography as="span" variant="caption" color="secondary">
              —
            </Typography>
          ),
      },
      {
        key: "documents",
        header: t("providers.columns.documents"),
        cell: (provider) => (
          <Typography as="span" variant="number">
            {provider._count.documents}
          </Typography>
        ),
      },
      {
        key: "team",
        header: t("providers.columns.team"),
        cell: (provider) => (
          <Typography as="span" variant="number">
            {provider._count.users}
          </Typography>
        ),
      },
      {
        key: "commission",
        header: t("providers.columns.commission"),
        cell: (provider) => {
          const rate = formatCommissionRate(provider.customCommissionRate);
          return rate ? (
            <Typography as="span" variant="number">
              {rate}
            </Typography>
          ) : (
            <Typography as="span" variant="caption" color="secondary">
              {t("providers.commission.platformDefault")}
            </Typography>
          );
        },
      },
      {
        key: "createdAt",
        header: t("providers.columns.joined"),
        cell: (provider) => (
          <Typography as="span" variant="number">
            {formatDay(provider.createdAt, language)}
          </Typography>
        ),
      },
    ],
    [t, language],
  );

  const isPendingQueue = statusFilter === ProviderStatus.PENDING_VERIFICATION;

  return (
    <div className="flex flex-col gap-6">
      {/* Status tabs = the "all providers" list and the review queue in one.
          The list scrolls horizontally on narrow screens rather than wrapping,
          so the tab row stays one predictable line. */}
      <Tabs
        value={statusFilter}
        onValueChange={(value) =>
          handleStatusFilterChange(value as StatusFilter)
        }
      >
        {/* py-1 keeps the active pill's shadow from being clipped by the
            scroll container (setting overflow-x also computes overflow-y). */}
        <div className="overflow-x-auto py-1">
          <TabsList>
            <TabsTrigger value={ALL_TAB}>
              {t("providers.filters.all")}
            </TabsTrigger>
            {PROVIDER_STATUS_TABS.map((status) => (
              <TabsTrigger key={status} value={status}>
                {t(`providers.status.${status}`)}
              </TabsTrigger>
            ))}
          </TabsList>
        </div>
      </Tabs>

      <DataTable
        mode="server"
        columns={columns}
        data={data?.data ?? []}
        totalCount={data?.total ?? 0}
        getRowId={(provider) => provider.id}
        query={query}
        onQueryChange={setQuery}
        searchable
        searchPlaceholder={t("providers.searchPlaceholder")}
        loading={isLoading}
        error={isError}
        onRetry={() => refetch()}
        onRowClick={(provider) =>
          router.push(ROUTES.ADMIN.PROVIDER_DETAIL(provider.id))
        }
        rowActions={(provider) => [
          {
            key: "view",
            label: t("providers.actions.view"),
            icon: <EyeIcon />,
            onSelect: () =>
              router.push(ROUTES.ADMIN.PROVIDER_DETAIL(provider.id)),
          },
          ...getStatusActions(provider.status).map((action) => {
            const ActionIcon = action.icon;
            return {
              key: action.confirmKey,
              label: t(action.labelKey),
              icon: <ActionIcon />,
              destructive: action.destructive,
              onSelect: () => openStatusAction(provider, action),
            };
          }),
        ]}
        // Only override the empty state for a genuinely empty review queue.
        // With a search active the DataTable's own "no results" copy is the
        // correct message, so leave it undefined and let it win.
        emptyState={
          isPendingQueue && !query.search.trim() ? (
            <EmptyState
              title={t("providers.emptyPendingTitle")}
              description={t("providers.emptyPendingDescription")}
            />
          ) : undefined
        }
      />

      {actionTarget && (
        <ProviderStatusConfirmDialog
          action={pendingAction}
          providerId={actionTarget.id}
          providerName={actionTarget.businessName}
          onClose={() => setPendingAction(null)}
        />
      )}
    </div>
  );
}
