"use client";

import * as React from "react";
import { PackageIcon, PencilIcon, PlusIcon, Trash2Icon } from "lucide-react";

import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
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 { useAdminPackages } from "@/hooks/catalog/useAdminPackages";
import { usePriceFormat } from "@/hooks/usePriceFormat";
import { useTranslation } from "@/hooks/useTranslation";
import { getPackageIcon } from "@/lib/constants/package-icons";
import type { WashPackage } from "@/types/catalog";

import { PackageDeleteDialog } from "./PackageDeleteDialog";
import { WashPackageFormDialog } from "./WashPackageFormDialog";

const ACTIVE_TABS = ["ALL", "ACTIVE", "INACTIVE"] as const;
type ActiveFilter = (typeof ACTIVE_TABS)[number];

/** `undefined` = no filter; the api layer stringifies the boolean */
const IS_ACTIVE_PARAM: Record<ActiveFilter, boolean | undefined> = {
  ALL: undefined,
  ACTIVE: true,
  INACTIVE: false,
};

/**
 * Admin service catalog — the packages every provider sells from.
 *
 * This is the source of the platform's service list and its pricing bounds:
 * the admin defines each package and the min/max a provider may charge, and
 * providers only opt in and pick a price inside that range
 * (`Notes/requitements/01_changes.txt`).
 *
 * Server mode: the backend owns search/filter/pagination. Columns are NOT
 * marked sortable — `GET /catalog/admin/packages` has no sort parameter (it
 * hardcodes `name asc`), and its `forbidNonWhitelisted` validation would 400
 * on an unexpected query key.
 *
 * The status column is read-only by design: `UpdateWashPackageDto` declares no
 * `isActive` and there is no activate/deactivate endpoint, so the API offers no
 * way to change it. Delete is the only lifecycle action available.
 */
export function CatalogView() {
  const { t } = useTranslation();
  const { formatPrice, formatPriceRange } = usePriceFormat();

  const { query, setQuery } = useDataTableQuery();
  const [activeFilter, setActiveFilter] = React.useState<ActiveFilter>("ALL");
  const [formOpen, setFormOpen] = React.useState(false);
  const [editing, setEditing] = React.useState<WashPackage | null>(null);
  const [deleteTarget, setDeleteTarget] = React.useState<WashPackage | null>(
    null,
  );

  const { data, isLoading, isError, refetch } = useAdminPackages({
    search: query.search,
    isActive: IS_ACTIVE_PARAM[activeFilter],
    page: query.page,
    limit: query.pageSize,
  });

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

  function openCreate() {
    setEditing(null);
    setFormOpen(true);
  }

  function openEdit(pkg: WashPackage) {
    setEditing(pkg);
    setFormOpen(true);
  }

  const columns = React.useMemo<DataTableColumn<WashPackage>[]>(
    () => [
      {
        // First column doubles as the mobile card title — keep it identifying.
        key: "name",
        header: t("catalog.columns.package"),
        cell: (pkg) => {
          const Icon = getPackageIcon(pkg.icon);
          return (
            <div className="flex min-w-0 items-center gap-2">
              <span className="flex size-9 shrink-0 items-center justify-center rounded-[12px] bg-information-light text-primary-sky-blue">
                <Icon className="size-4" />
              </span>
              <div className="flex min-w-0 flex-col gap-1">
                <Typography as="span" variant="body" className="truncate">
                  {pkg.name}
                </Typography>
                {pkg.description && (
                  <Typography
                    as="span"
                    variant="caption"
                    color="secondary"
                    className="truncate"
                  >
                    {pkg.description}
                  </Typography>
                )}
              </div>
            </div>
          );
        },
      },
      {
        key: "duration",
        header: t("catalog.columns.duration"),
        cell: (pkg) => (
          <Typography as="span" variant="number">
            {t("catalog.minutes", { count: pkg.estimatedDuration })}
          </Typography>
        ),
      },
      {
        key: "priceRange",
        header: t("catalog.columns.priceRange"),
        cell: (pkg) => (
          <Typography as="span" variant="number">
            {pkg.minPrice === pkg.maxPrice
              ? formatPrice(pkg.minPrice)
              : formatPriceRange(pkg.minPrice, pkg.maxPrice)}
          </Typography>
        ),
      },
      {
        key: "features",
        header: t("catalog.columns.features"),
        hideOnMobile: true,
        // Capped: a package with six features would otherwise stretch the table
        // past its container and force a horizontal scroll for one text cell.
        // The full list is one click away in the edit dialog.
        className: "max-w-[320px]",
        cell: (pkg) =>
          pkg.features.length > 0 ? (
            <Typography
              as="p"
              variant="caption"
              color="secondary"
              className="truncate"
              title={pkg.features.join(" • ")}
            >
              {pkg.features.join(" • ")}
            </Typography>
          ) : (
            <Typography as="span" variant="caption" color="secondary">
              —
            </Typography>
          ),
      },
      {
        key: "status",
        header: t("catalog.columns.status"),
        cell: (pkg) => (
          <Badge variant={pkg.isActive ? "complete" : "closed"}>
            {pkg.isActive
              ? t("catalog.status.active")
              : t("catalog.status.inactive")}
          </Badge>
        ),
      },
    ],
    [t, formatPrice, formatPriceRange],
  );

  return (
    <div className="flex flex-col gap-6">
      {/* py-1 keeps the active pill's shadow from being clipped by the
          scroll container (setting overflow-x also computes overflow-y). */}
      <Tabs
        value={activeFilter}
        onValueChange={(value) =>
          handleActiveFilterChange(value as ActiveFilter)
        }
      >
        <div className="overflow-x-auto py-1">
          <TabsList>
            {ACTIVE_TABS.map((tab) => (
              <TabsTrigger key={tab} value={tab}>
                {t(`catalog.filters.${tab}`)}
              </TabsTrigger>
            ))}
          </TabsList>
        </div>
      </Tabs>

      <DataTable
        mode="server"
        columns={columns}
        data={data?.data ?? []}
        totalCount={data?.total ?? 0}
        getRowId={(pkg) => pkg.id}
        query={query}
        onQueryChange={setQuery}
        searchable
        searchPlaceholder={t("catalog.searchPlaceholder")}
        toolbar={
          <Button onClick={openCreate}>
            <PlusIcon />
            {t("catalog.actions.new")}
          </Button>
        }
        loading={isLoading}
        error={isError}
        onRetry={() => refetch()}
        onRowClick={openEdit}
        rowActions={(pkg) => [
          {
            key: "edit",
            label: t("catalog.actions.edit"),
            icon: <PencilIcon />,
            onSelect: () => openEdit(pkg),
          },
          {
            key: "delete",
            label: t("catalog.actions.delete"),
            icon: <Trash2Icon />,
            destructive: true,
            onSelect: () => setDeleteTarget(pkg),
          },
        ]}
        // Only override the empty state for a genuinely empty catalog. With a
        // search active the DataTable's own "no results" copy is the correct
        // message, so leave it undefined and let it win.
        emptyState={
          !query.search.trim() ? (
            <EmptyState
              icon={<PackageIcon />}
              title={t("catalog.emptyTitle")}
              description={t("catalog.emptyDescription")}
              action={
                <Button className="w-full" onClick={openCreate}>
                  <PlusIcon />
                  {t("catalog.actions.new")}
                </Button>
              }
            />
          ) : undefined
        }
      />

      <WashPackageFormDialog
        open={formOpen}
        onOpenChange={setFormOpen}
        editing={editing}
      />

      <PackageDeleteDialog
        target={deleteTarget}
        onClose={() => setDeleteTarget(null)}
      />
    </div>
  );
}
