"use client";

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

import { ListPageCard } from "@/app/dashboard/_components";
import { UploadXmlQuickFilters } from "@/components/xml-apis/upload-xml/components/upload-xml-quick-filters";
import { UploadXmlTable } from "@/components/xml-apis/upload-xml/components/upload-xml-table";
import { UploadXmlToolbar } from "@/components/xml-apis/upload-xml/components/upload-xml-toolbar";
import {
  buildUploadXmlListHref,
  nextUploadXmlListSort,
  parseUploadXmlListFilters,
  parseUploadXmlListSort,
} from "@/components/xml-apis/upload-xml/data/upload-xml-list-filters";
import { useUploadXml } from "@/components/xml-apis/upload-xml/hooks/use-upload-xml";
import { XmlApiErrorBanner } from "@/components/xml-apis/shared/xml-api-error-banner";
import type {
  UploadXml,
  UploadXmlBankQuickFilter,
  UploadXmlDateQuickFilter,
  UploadXmlListFilters,
  UploadXmlListSort,
  UploadXmlSortField,
} from "@/components/xml-apis/upload-xml/types";
import { Skeleton } from "@/components/ui/skeleton";

type UploadXmlListPageProps = {
  initialData?: UploadXml[];
  initialTotalCount?: number;
  initialPage?: number;
  initialPageSize?: number;
  initialPageCount?: number;
  initialErrorMessage?: string | null;
  initialFilters?: UploadXmlListFilters;
  initialSort?: UploadXmlListSort;
  dateQuickFilters?: UploadXmlDateQuickFilter[];
  bankQuickFilters?: UploadXmlBankQuickFilter[];
};

function UploadXmlListContent({
  initialData = [],
  initialTotalCount = 0,
  initialPage = 1,
  initialPageSize = 20,
  initialPageCount = 1,
  initialErrorMessage = null,
  initialFilters = {},
  initialSort = {},
  dateQuickFilters: initialDateQuickFilters = [],
  bankQuickFilters: initialBankQuickFilters = [],
}: UploadXmlListPageProps) {
  const router = useRouter();
  const searchParams = useSearchParams();
  const [isPending, startTransition] = useTransition();

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

  const sort = React.useMemo(() => {
    const fromUrl = parseUploadXmlListSort(searchParams);
    const hasUrlSort = Boolean(fromUrl.field && fromUrl.dir);
    return hasUrlSort ? fromUrl : initialSort;
  }, [initialSort, 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,
    isRefreshing,
    refresh,
    removeLocal,
    patchLocal,
    dateQuickFilters,
    bankQuickFilters,
  } = useUploadXml({
    initialData,
    initialTotalCount,
    initialPage,
    initialPageSize,
    initialPageCount,
    filters,
    sort,
    dateQuickFilters: initialDateQuickFilters,
    bankQuickFilters: initialBankQuickFilters,
  });

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

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

  const handleSortChange = React.useCallback(
    (field: UploadXmlSortField) => {
      navigateList(
        {
          sort: nextUploadXmlListSort(sort, field),
          page: 1,
        },
        { replace: true },
      );
    },
    [navigateList, sort],
  );

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

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

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

  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],
  );

  return (
    <ListPageCard
      icon={Upload}
      title="Upload XML"
      description="Browse uploaded bank XML files, import, compare, and manage records."
      breadcrumb={[{ label: "XML API" }, { label: "Upload XML" }]}
      actions={
        <UploadXmlToolbar
          isRefreshing={isRefreshing}
          onRefresh={() => void refresh()}
        />
      }
      subNav={
        <UploadXmlQuickFilters
          filters={filters}
          dateQuickFilters={dateQuickFilters}
          bankQuickFilters={bankQuickFilters}
          onFiltersChange={handleFilterChange}
        />
      }
    >
      <XmlApiErrorBanner message={initialErrorMessage} />
      <UploadXmlTable
        data={data}
        totalCount={totalCount}
        page={page}
        pageSize={pageSize}
        pageCount={pageCount}
        isLoading={isPending || isRefreshing}
        filters={filters}
        onFiltersChange={handleFilterChange}
        onDelete={removeLocal}
        onDeleteTemp={(id) => patchLocal(id, { inserted: false })}
        sort={sort}
        onSortChange={handleSortChange}
        onPageChange={handlePageChange}
        onPageSizeChange={handlePageSizeChange}
      />
    </ListPageCard>
  );
}

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