"use client";

import * as React from "react";
import { usePathname, useRouter, useSearchParams } from "next/navigation";

import type { PaginationState, SortingState } from "@tanstack/react-table";

import { CustomerAssetServerListTable } from "@/app/customer/_components/customer-asset-server-list-table";

import { useCashList } from "../../_lib/use-cash-list";
import { saveCashColumnPrefsClient } from "../../_lib/cash-api";
import {
  buildCashPageSearchParams,
  DEFAULT_CASH_PAGE_SIZE,
  DEFAULT_CASH_SORTING,
  parseCashPageStateFromSearchParams,
} from "../../_lib/cash-filters";
import { createCashColumns, FALLBACK_CASH_GRID_COLUMNS } from "./columns";
import { CashDetailSheet } from "./cash-detail-sheet";
import { usePortfolioScopePageReset } from "@/app/customer/_lib/admin/use-portfolio-scope-page-reset";

const EMPTY_FILTER_OPTIONS = {
  banks: [{ value: "All", label: "All" }],
  types: [{ value: "All", label: "All" }],
  executionTypes: [{ value: "All", label: "All" }],
  transactions: [{ value: "All", label: "All" }],
};

export function ListCashTable({
  accountId,
  bankId,
}: {
  accountId?: string;
  bankId?: string;
} = {}) {
  const router = useRouter();
  const pathname = usePathname();
  const searchParams = useSearchParams();
  const [initialPageState] = React.useState(() => parseCashPageStateFromSearchParams(searchParams));
  const lastSyncedSearchParamsRef = React.useRef(searchParams.toString());

  const isHydratingFromUrlRef = React.useRef(false);

  const [pagination, setPagination] = React.useState<PaginationState>(initialPageState.pagination);
  const [sorting, setSorting] = React.useState<SortingState>(initialPageState.sorting);

  usePortfolioScopePageReset(
    React.useCallback(() => {
      const parsed = parseCashPageStateFromSearchParams(new URLSearchParams());
      isHydratingFromUrlRef.current = true;
      lastSyncedSearchParamsRef.current = "__scope_reset__";
      setPagination(parsed.pagination);
      setSorting(parsed.sorting);
      router.replace(pathname, { scroll: false });
    }, [pathname, router]),
  );

  React.useEffect(() => {
    setPagination((current) =>
      current.pageIndex === 0 ? current : { ...current, pageIndex: 0 },
    );
  }, [accountId, bankId]);

  React.useEffect(() => {
    const current = searchParams.toString();
    if (current === lastSyncedSearchParamsRef.current) {
      return;
    }

    const parsed = parseCashPageStateFromSearchParams(searchParams);
    isHydratingFromUrlRef.current = true;
    lastSyncedSearchParamsRef.current = current;

    setPagination(parsed.pagination);
    setSorting((currentSort) =>
      currentSort[0]?.id === parsed.sorting[0]?.id && currentSort[0]?.desc === parsed.sorting[0]?.desc
        ? currentSort
        : parsed.sorting,
    );
  }, [searchParams]);

  React.useEffect(() => {
    if (isHydratingFromUrlRef.current) {
      isHydratingFromUrlRef.current = false;
      return;
    }

    const nextSearchParams = buildCashPageSearchParams({ pagination, sorting }).toString();
    if (nextSearchParams === lastSyncedSearchParamsRef.current) {
      return;
    }

    lastSyncedSearchParamsRef.current = nextSearchParams;
    const href = nextSearchParams ? `${pathname}?${nextSearchParams}` : pathname;
    router.replace(href, { scroll: false });
  }, [pagination, pathname, router, sorting]);

  const { rows, setRows, totalCount, pageCount, gridColumns, columnPrefs, isLoading, errorMessage, refresh } =
    useCashList({
    pagination,
    sorting,
    accountId,
    bankId,
  });

  const failedPageRef = React.useRef<number | null>(null);

  React.useEffect(() => {
    if (!errorMessage || pagination.pageIndex === 0) {
      if (!errorMessage) failedPageRef.current = null;
      return;
    }

    if (failedPageRef.current === pagination.pageIndex) return;
    failedPageRef.current = pagination.pageIndex;
    setPagination((current) => ({ ...current, pageIndex: 0 }));
  }, [errorMessage, pagination.pageIndex]);

  const catalog = React.useMemo(() => {
    const source = gridColumns.length ? gridColumns : FALLBACK_CASH_GRID_COLUMNS;
    const allowed = new Set(FALLBACK_CASH_GRID_COLUMNS.map((column) => column.key));
    return source.filter((column) => allowed.has(column.key));
  }, [gridColumns]);

  const columnFactory = React.useCallback(
    ({
      onView,
      onEdit,
    }: {
      onView: (row: (typeof rows)[number]) => void;
      onEdit: (row: (typeof rows)[number]) => void;
    }) => createCashColumns(catalog, onView, onEdit),
    [catalog],
  );

  const savePrefs = React.useCallback(
    async (prefs: { visibility: Record<string, boolean>; order: string[] }) => {
      await saveCashColumnPrefsClient(prefs);
    },
    [],
  );

  const handleRefreshReset = React.useCallback(() => {
    lastSyncedSearchParamsRef.current = "__scope_reset__";
    setPagination({ pageIndex: 0, pageSize: DEFAULT_CASH_PAGE_SIZE });
    setSorting(DEFAULT_CASH_SORTING);
    router.replace(pathname, { scroll: false });
    // Resetting to values already in state is a no-op React bails out of, so
    // without this the Refresh button does nothing once page/sort are default.
    refresh();
  }, [pathname, refresh, router]);

  const server = React.useMemo(
    () => ({
      rows,
      setRows,
      totalCount,
      pageCount,
      isLoading,
      errorMessage,
      refresh,
      onRefreshClick: handleRefreshReset,
      canCreate: false,
      pagination,
      setPagination,
      sorting,
      setSorting,
      getFilterValue: () => "",
      onColumnFilterChange: () => undefined,
      placementDateRange: undefined,
      onPlacementDateRangeChange: () => undefined,
      filterOptions: EMPTY_FILTER_OPTIONS,
      showParentIsinFilter: false,
      showFilterRow: false,
    }),
    [
      errorMessage,
      handleRefreshReset,
      isLoading,
      pageCount,
      pagination,
      refresh,
      rows,
      setRows,
      sorting,
      totalCount,
    ],
  );

  return (
    <CustomerAssetServerListTable
      title="Cash Transaction"
      emptyMessage="No cash records found."
      rowsPerPageId="cash-rows-per-page"
      moduleId="cash"
      singularName="Cash"
      editMode="placeholder"
      columnFactory={columnFactory}
      DetailSheet={CashDetailSheet}
      server={server}
      columnPrefs={{
        catalog,
        initialPrefs: columnPrefs,
        savePrefs,
        lockedKeys: [],
      }}
    />
  );
}
