"use client";

import { Database, X } from "lucide-react";
import Link from "next/link";
import { useRouter, useSearchParams } from "next/navigation";
import * as React from "react";
import { Suspense, useTransition } from "react";

import { ListPageCard } from "@/app/dashboard/_components";
import { Badge } from "@/components/ui/badge";
import { buttonVariants } from "@/components/ui/button";
import { Skeleton } from "@/components/ui/skeleton";
import { TempDataTable } from "@/components/xml-apis/temp-data/components/temp-data-table";
import {
  buildTempDataListHref,
  parseTempDataListFilters,
} from "@/components/xml-apis/temp-data/data/temp-data-list-filters";
import { useTempData } from "@/components/xml-apis/temp-data/hooks/use-temp-data";
import { XmlApiErrorBanner } from "@/components/xml-apis/shared/xml-api-error-banner";
import type {
  TempDataBankOption,
  TempDataClassSummary,
  TempDataListFilters,
  TempDataRow,
  TempDataStatsRangeMeta,
  TempDataSummary,
} from "@/components/xml-apis/temp-data/types";
import { FRONTEND_ROUTES } from "@/config/frontend-routes";
import { cn } from "@/lib/utils";

const EMPTY_ROWS: TempDataRow[] = [];
const EMPTY_CLASS_SUMMARY: TempDataClassSummary[] = [];
const EMPTY_BANK_OPTIONS: TempDataBankOption[] = [];

type TempDataListPageProps = {
  initialData?: TempDataRow[];
  initialTotalCount?: number;
  initialPage?: number;
  initialPageSize?: number;
  initialPageCount?: number;
  initialPageHeading?: string;
  initialAttributeLabels?: Record<string, string>;
  initialModuleList?: Record<string, string>;
  initialSummary?: TempDataSummary;
  initialClassSummary?: TempDataClassSummary[];
  initialBankApiOptions?: TempDataBankOption[];
  initialStatsRangeMeta?: TempDataStatsRangeMeta;
  initialInsertMissingEnabled?: boolean;
  initialErrorMessage?: string | null;
  initialFilters?: TempDataListFilters;
  /** When true, fetch via /temp-data/list proxy on mount (skip SSR Yii fetch). */
  loadFromProxy?: boolean;
  /** Render only banner + table (without outer ListPageCard wrapper). */
  tableOnly?: boolean;
};

function TempDataListContent({
  initialData = EMPTY_ROWS,
  initialTotalCount = 0,
  initialPage = 1,
  initialPageSize = 100,
  initialPageCount = 1,
  initialPageHeading,
  initialAttributeLabels,
  initialModuleList,
  initialSummary,
  initialClassSummary = EMPTY_CLASS_SUMMARY,
  initialBankApiOptions = EMPTY_BANK_OPTIONS,
  initialStatsRangeMeta,
  initialInsertMissingEnabled = true,
  initialErrorMessage = null,
  initialFilters = {},
  loadFromProxy = false,
  tableOnly = false,
}: TempDataListPageProps) {
  const router = useRouter();
  const searchParams = useSearchParams();
  const [isPending, startTransition] = useTransition();

  const filters = React.useMemo(() => {
    const fromUrl = parseTempDataListFilters(searchParams);
    const hasUrlFilters = Object.values(fromUrl).some(Boolean);
    return hasUrlFilters ? fromUrl : initialFilters;
  }, [initialFilters, searchParams]);

  const pageFromUrl = Number(searchParams.get("page") ?? String(initialPage));
  const pageSizeFromUrl = Number(
    searchParams.get("page_size") ?? String(initialPageSize),
  );
  const urlPage =
    Number.isFinite(pageFromUrl) && pageFromUrl > 0 ? pageFromUrl : initialPage;
  const urlPageSize =
    Number.isFinite(pageSizeFromUrl) && pageSizeFromUrl > 0
      ? pageSizeFromUrl
      : initialPageSize;

  const {
    data,
    totalCount,
    page,
    pageSize,
    pageCount,
    pageHeading,
    attributeLabels,
    moduleList,
    summary,
    classSummary,
    bankApiOptions,
    statsRangeMeta,
    insertMissingEnabled,
    isLoading,
    isRefreshing,
    refresh,
    removeLocal,
  } = useTempData({
    initialData,
    initialTotalCount,
    initialPage,
    initialPageSize,
    initialPageCount,
    initialPageHeading,
    initialAttributeLabels,
    initialModuleList,
    initialSummary,
    initialClassSummary,
    initialBankApiOptions,
    initialStatsRangeMeta,
    initialInsertMissingEnabled,
    filters,
    page: urlPage,
    pageSize: urlPageSize,
    loadFromProxy,
  });

  const navigateList = React.useCallback(
    (
      next: {
        filters?: TempDataListFilters;
        page?: number;
        pageSize?: number;
      },
      options?: { replace?: boolean },
    ) => {
      const href = buildTempDataListHref(next.filters ?? filters, {
        page: next.page ?? urlPage,
        pageSize: next.pageSize ?? urlPageSize,
      });

      startTransition(() => {
        if (options?.replace) {
          router.replace(href, { scroll: false });
          return;
        }
        router.push(href, { scroll: false });
      });
    },
    [filters, router, urlPage, urlPageSize],
  );

  const handleFilterChange = React.useCallback(
    (updates: Partial<TempDataListFilters>) => {
      const nextFilters: TempDataListFilters = { ...filters };

      for (const [key, value] of Object.entries(updates) as Array<
        [
          keyof TempDataListFilters,
          TempDataListFilters[keyof TempDataListFilters],
        ]
      >) {
        if (
          value === undefined ||
          value === null ||
          value === "" ||
          (key === "inserted" && value === "all")
        ) {
          delete nextFilters[key];
        } else {
          nextFilters[key] = value as never;
        }
      }

      navigateList(
        {
          filters: nextFilters,
          page: 1,
        },
        { replace: true },
      );
    },
    [filters, navigateList],
  );

  const handleAssetClassFilter = React.useCallback(
    (code: string) => {
      const nextCode = filters.assetClass === code ? undefined : code;
      handleFilterChange({
        assetClass: nextCode,
        inserted: nextCode ? "not_inserted" : filters.inserted,
      });
    },
    [filters.assetClass, filters.inserted, handleFilterChange],
  );

  const handlePageChange = React.useCallback(
    (nextPage: number) => {
      if (nextPage < 1 || nextPage > pageCount || nextPage === page) return;
      navigateList({ page: nextPage });
    },
    [navigateList, page, pageCount],
  );

  const handlePageSizeChange = React.useCallback(
    (nextPageSize: number) => {
      if (nextPageSize === pageSize) return;
      navigateList({ page: 1, pageSize: nextPageSize }, { replace: true });
    },
    [navigateList, pageSize],
  );

  const xmlIdFilter = filters.xmlId?.trim() || undefined;
  const xmlUploadIdFilter =
    xmlIdFilter && /^\d+$/.test(xmlIdFilter) ? xmlIdFilter : undefined;
  const insertedFilter = filters.inserted ?? "all";

  const tableContent = (
    <>
      <XmlApiErrorBanner message={initialErrorMessage} />
      {xmlIdFilter ? (
        <div className="mb-3 flex flex-wrap items-center gap-2 rounded-md border border-border/60 bg-muted/40 px-3 py-2 text-sm">
          <span className="text-muted-foreground">Filtered by</span>
          <Badge
            variant="secondary"
            className="max-w-[420px] truncate font-mono"
            title={xmlIdFilter}
          >
            {xmlUploadIdFilter ? `XML ID ${xmlUploadIdFilter}` : xmlIdFilter}
          </Badge>
          {xmlUploadIdFilter ? (
            <Link
              href={FRONTEND_ROUTES.xmlApis.uploadXml.importView(
                xmlUploadIdFilter,
              )}
              className={cn(
                buttonVariants({ variant: "link" }),
                "h-auto px-0 text-xs",
              )}
            >
              Open upload
            </Link>
          ) : null}
          <button
            type="button"
            onClick={() => handleFilterChange({ xmlId: undefined })}
            className={cn(
              buttonVariants({ variant: "ghost", size: "sm" }),
              "ml-auto h-7 gap-1 text-xs",
            )}
          >
            <X className="size-3.5" />
            Clear filter
          </button>
        </div>
      ) : null}
      <TempDataTable
        data={data}
        totalCount={totalCount}
        page={page}
        pageSize={pageSize}
        pageCount={pageCount}
        attributeLabels={attributeLabels}
        moduleList={moduleList}
        summary={summary}
        classSummary={classSummary}
        bankApiOptions={bankApiOptions}
        statsRangeMeta={statsRangeMeta}
        filters={filters}
        insertedFilter={insertedFilter}
        insertMissingEnabled={insertMissingEnabled}
        // Only block the table on the empty initial load. Filter/page refreshes must
        // keep inputs focusable (layout uses pointer-events-none while isLoading).
        isLoading={(isLoading || isPending) && data.length === 0}
        isRefreshing={isPending || isLoading || isRefreshing}
        onRefresh={() => void refresh()}
        onFiltersChange={handleFilterChange}
        onAssetClassFilter={handleAssetClassFilter}
        onDelete={removeLocal}
        onPageChange={handlePageChange}
        onPageSizeChange={handlePageSizeChange}
      />
    </>
  );

  if (tableOnly) {
    return tableContent;
  }

  return (
    <ListPageCard
      icon={Database}
      title={pageHeading ?? "All Bank Temp Data"}
      description="Review temporary rows from XML imports, then promote eligible ones into live customer books."
      breadcrumb={[{ label: "XML API" }, { label: "Temp Data" }]}
    >
      {tableContent}
    </ListPageCard>
  );
}

export function TempDataListPage(props: TempDataListPageProps) {
  return (
    <Suspense fallback={<Skeleton className="h-64 w-full rounded-lg" />}>
      <TempDataListContent {...props} />
    </Suspense>
  );
}
