"use client";

import { FileStack } from "lucide-react";
import Link from "next/link";
import { useRouter, useSearchParams } from "next/navigation";
import { Suspense, useCallback, useMemo, useTransition } from "react";

import { ListPageCard } from "@/app/dashboard/_components";
import { Button } from "@/components/ui/button";
import { TABLE_TOOLBAR_BTN_OUTLINE } from "@/components/shared/table-ui";
import {
  buildAssetXmlUploadListHref,
  buildAssetXmlUploadViewHref,
  parseAssetXmlBankListFilters,
  parseAssetXmlUploadListFilters,
} from "@/components/xml-apis/asset-xml-upload/data/asset-xml-upload-list-filters";
import { AssetXmlBankValuesTable } from "@/components/xml-apis/asset-xml-upload/components/asset-xml-bank-values-table";
import { AssetXmlUploadTable } from "@/components/xml-apis/asset-xml-upload/components/asset-xml-upload-table";
import { XmlApiCreateRefreshToolbar } from "@/components/xml-apis/shared/xml-api-create-refresh-toolbar";
import {
  ASSET_XML_AVAILABLE_BANKS,
  getAssetXmlBankByBankId,
  getAssetXmlBankSlugById,
  resolveAssetXmlBankId,
  type AssetXmlBankListFilters,
} from "@/components/xml-apis/asset-xml-upload/data/asset-xml-upload-banks";
import { useAssetXmlBankValues } from "@/components/xml-apis/asset-xml-upload/hooks/use-asset-xml-bank-values";
import { useAssetXmlUpload } from "@/components/xml-apis/asset-xml-upload/hooks/use-asset-xml-upload";
import { XmlApiErrorBanner } from "@/components/xml-apis/shared/xml-api-error-banner";
import type {
  AssetXmlUpload,
  AssetXmlUploadListFilters,
  AssetXmlUploadViewData,
} from "@/components/xml-apis/asset-xml-upload/types";
import { Skeleton } from "@/components/ui/skeleton";

const ASSET_XML_LIST_HREF = "/dashboard/xml-apis/asset-xml-upload";
// Stable defaults: fresh literals would change identity every render and
// retrigger the render-phase prop resync in useXmlApiPaginatedList forever.
const NO_UPLOADS: AssetXmlUpload[] = [];
const NO_LIST_FILTERS: AssetXmlUploadListFilters = {};

type AssetXmlUploadListPageProps = {
  initialData?: AssetXmlUpload[];
  initialTotalCount?: number;
  initialPage?: number;
  initialPageSize?: number;
  initialPageCount?: number;
  initialErrorMessage?: string | null;
  bankId?: string;
  filters?: AssetXmlBankListFilters;
  listFilters?: AssetXmlUploadListFilters;
  initialBankView?: AssetXmlUploadViewData | null;
};

function AssetXmlUploadListContent({
  initialData = NO_UPLOADS,
  initialTotalCount = 0,
  initialPage = 1,
  initialPageSize = 10,
  initialPageCount = 1,
  initialErrorMessage = null,
  bankId: initialBankId,
  listFilters: initialListFilters = NO_LIST_FILTERS,
  initialBankView = null,
}: AssetXmlUploadListPageProps) {
  const searchParams = useSearchParams();
  const router = useRouter();
  const [, startTransition] = useTransition();
  const queryKey = searchParams.toString();
  const bankId =
    resolveAssetXmlBankId(
      searchParams.get("bank_id") ?? searchParams.get("bank"),
    ) ?? initialBankId;
  const filters = useMemo(
    () => (bankId ? parseAssetXmlBankListFilters(searchParams) : {}),
    [bankId, queryKey],
  );
  const listFilters = useMemo(() => {
    const fromUrl = parseAssetXmlUploadListFilters(searchParams);
    const hasUrlFilters = Object.values(fromUrl).some(Boolean);
    return hasUrlFilters ? fromUrl : initialListFilters;
  }, [initialListFilters, queryKey, searchParams]);
  const currentPage = useMemo(
    () => Number(searchParams.get("page") ?? initialPage),
    [initialPage, queryKey],
  );
  const currentPageSize = useMemo(() => {
    const fallback = bankId ? 20 : initialPageSize;
    return Number(searchParams.get("page_size") ?? fallback);
  }, [bankId, initialPageSize, queryKey]);
  const activeBankId =
    getAssetXmlBankSlugById(bankId ?? "") ??
    searchParams.get("bank") ??
    undefined;
  const bank = bankId ? getAssetXmlBankByBankId(bankId) : undefined;

  const uploadList = useAssetXmlUpload({
    initialData,
    initialTotalCount,
    initialPage,
    initialPageSize,
    initialPageCount,
    filters: listFilters,
  });

  const bankValues = useAssetXmlBankValues({
    bankId: bankId ?? "",
    queryKey,
    page: currentPage,
    pageSize: currentPageSize,
    filters,
    initialBankView,
    initialTotalCount,
    initialPageCount,
  });

  const navigateUploadList = useCallback(
    (
      next: {
        filters?: AssetXmlUploadListFilters;
        page?: number;
        pageSize?: number;
      },
      options?: { replace?: boolean },
    ) => {
      const href = buildAssetXmlUploadListHref(next.filters ?? listFilters, {
        page: next.page ?? currentPage,
        pageSize: next.pageSize ?? currentPageSize,
      });
      startTransition(() => {
        if (options?.replace) {
          router.replace(href, { scroll: false });
          return;
        }
        router.push(href, { scroll: false });
      });
    },
    [currentPage, currentPageSize, listFilters, router],
  );

  const handleListFilterChange = useCallback(
    (updates: Partial<AssetXmlUploadListFilters>) => {
      const nextFilters: AssetXmlUploadListFilters = { ...listFilters };
      for (const [key, value] of Object.entries(updates) as Array<
        [
          keyof AssetXmlUploadListFilters,
          AssetXmlUploadListFilters[keyof AssetXmlUploadListFilters],
        ]
      >) {
        if (value === undefined || value === null || value === "") {
          delete nextFilters[key];
        } else {
          nextFilters[key] = value;
        }
      }
      navigateUploadList({ filters: nextFilters, page: 1 }, { replace: true });
    },
    [listFilters, navigateUploadList],
  );

  const handleUploadPageChange = useCallback(
    (nextPage: number) => {
      if (
        nextPage < 1 ||
        nextPage > uploadList.pageCount ||
        nextPage === uploadList.page
      ) {
        return;
      }
      navigateUploadList({ page: nextPage });
    },
    [navigateUploadList, uploadList.page, uploadList.pageCount],
  );

  const handleUploadPageSizeChange = useCallback(
    (nextPageSize: number) => {
      if (nextPageSize === currentPageSize) return;
      navigateUploadList({ page: 1, pageSize: nextPageSize }, { replace: true });
    },
    [currentPageSize, navigateUploadList],
  );

  const handleReupdateValues = (id: string, bankApiId?: string) => {
    router.push(
      buildAssetXmlUploadViewHref({
        uploadId: id,
        reupdate: true,
        bankId: bankApiId,
      }),
    );
  };

  const isBankView = Boolean(bankId);
  const pageTitle = isBankView
    ? (bankValues.bankView?.title ??
      `${bank?.label ?? "Bank"} Asset XML Values`)
    : "Asset XML Upload";
  const pageDescription = isBankView
    ? `Browse parsed asset XML values for ${bank?.label ?? "the selected bank"}.`
    : "Upload and manage asset XML files by bank. Import, filter, and delete records.";

  return (
    <ListPageCard
      icon={FileStack}
      title={pageTitle}
      description={pageDescription}
      breadcrumb={[{ label: "XML API" }, { label: "Asset XML Upload" }]}
      actions={
        <XmlApiCreateRefreshToolbar
          listHref={ASSET_XML_LIST_HREF}
          isRefreshing={
            isBankView ? bankValues.isRefreshing : uploadList.isRefreshing
          }
          onRefresh={() =>
            void (isBankView ? bankValues.refresh() : uploadList.refresh())
          }
          leadingActions={ASSET_XML_AVAILABLE_BANKS.map((bank) => (
            <Button
              key={bank.id}
              {...TABLE_TOOLBAR_BTN_OUTLINE}
              variant={activeBankId === bank.id ? "default" : "outline"}
              asChild
            >
              <Link href={`${ASSET_XML_LIST_HREF}?bank=${bank.id}`}>
                List {bank.label}
              </Link>
            </Button>
          ))}
        />
      }
    >
      <XmlApiErrorBanner message={initialErrorMessage} />

      {isBankView && bankValues.bankView ? (
        <AssetXmlBankValuesTable
          bankView={bankValues.bankView}
          totalCount={bankValues.totalCount}
          page={bankValues.page}
          pageSize={bankValues.pageSize}
          pageCount={bankValues.pageCount}
          isLoading={bankValues.isLoading || bankValues.isRefreshing}
          onPageChange={bankValues.goToPage}
          onPageSizeChange={bankValues.changePageSize}
        />
      ) : isBankView ? (
        <Skeleton className="h-64 w-full rounded-lg" />
      ) : (
        <AssetXmlUploadTable
          data={uploadList.data}
          totalCount={uploadList.totalCount}
          page={uploadList.page}
          pageSize={uploadList.pageSize}
          pageCount={uploadList.pageCount}
          filters={listFilters}
          isLoading={uploadList.isLoading || uploadList.isRefreshing}
          onDelete={uploadList.removeLocal}
          onDeleteTemp={(id) => uploadList.patchLocal(id, { inserted: false })}
          onReupdateValues={handleReupdateValues}
          onFilterChange={handleListFilterChange}
          onPageChange={handleUploadPageChange}
          onPageSizeChange={handleUploadPageSizeChange}
        />
      )}
    </ListPageCard>
  );
}

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