"use client";

import { toastApiError } from "@/lib/toast-api-error";
import * as React from "react";

import {
  getCoreRowModel,
  useReactTable,
  type Header,
  type PaginationState,
} from "@tanstack/react-table";

import {
  DataTablePagination,
  DataTableShell,
  useDebouncedValue,
} from "@/app/dashboard/_components/data-table";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select";
import { TableCell } from "@/components/ui/table";
import { useRouter } from "next/navigation";

import { missingAssetMarketDataColumns } from "./columns";
import {
  BASE_ASSET_CLASS_FILTER_OPTIONS,
  buildMissingAssetMarketDataHref,
  DEFAULT_PAGE_SIZE,
} from "./constants";
import { exportMissingAssetMarketDataCsv } from "./export-csv";
import { formatPlainAmount } from "@/lib/format/numbers";
import {
  type MissingAssetMarketDataFilters,
  type MissingAssetMarketDataRow,
} from "./schema";

type Props = {
  data: MissingAssetMarketDataRow[];
  filters: MissingAssetMarketDataFilters;
  totalCount: number;
  page: number;
  pageSize: number;
  pageCount: number;
};

export function MissingAssetMarketDataTable({
  data,
  filters,
  totalCount,
  page,
  pageSize,
  pageCount,
}: Props) {
  const router = useRouter();
  const [isExporting, setIsExporting] = React.useState(false);
  const [isinDraft, setIsinDraft] = React.useState(filters.isin);
  const debouncedIsin = useDebouncedValue(isinDraft);

  const navigate = React.useCallback(
    (
      next: {
        isin?: string;
        baseAssetClass?: MissingAssetMarketDataFilters["baseAssetClass"];
        page?: number;
        pageSize?: number;
      },
      options?: { replace?: boolean },
    ) => {
      const href = buildMissingAssetMarketDataHref({
        isin: next.isin ?? filters.isin,
        baseAssetClass: next.baseAssetClass ?? filters.baseAssetClass,
        page: next.page ?? page,
        pageSize: next.pageSize ?? pageSize,
      });

      if (options?.replace) {
        router.replace(href, { scroll: false });
        return;
      }

      router.push(href, { scroll: false });
    },
    [filters.baseAssetClass, filters.isin, page, pageSize, router],
  );

  React.useEffect(() => {
    setIsinDraft(filters.isin);
  }, [filters.isin]);

  React.useEffect(() => {
    const normalizedIsin = debouncedIsin.trim();
    if (normalizedIsin === filters.isin) {
      return;
    }

    navigate(
      {
        isin: normalizedIsin,
        page: 1,
      },
      { replace: true },
    );
  }, [debouncedIsin, filters.isin, navigate]);

  const pagination = React.useMemo<PaginationState>(
    () => ({
      pageIndex: Math.max(page - 1, 0),
      pageSize,
    }),
    [page, pageSize],
  );

  const table = useReactTable({
    data,
    columns: missingAssetMarketDataColumns,
    state: { pagination },
    pageCount,
    manualPagination: true,
    onPaginationChange: (updater) => {
      const next =
        typeof updater === "function" ? updater(pagination) : updater;
      const nextPageSize = next.pageSize > 0 ? next.pageSize : pageSize;
      const nextPage =
        nextPageSize !== pageSize ? 1 : Math.max(next.pageIndex + 1, 1);

      navigate({
        page: nextPage,
        pageSize: nextPageSize,
      });
    },
    getCoreRowModel: getCoreRowModel(),
    getRowId: (row) => row.id,
  });

  const exportFiltered = async () => {
    setIsExporting(true);
    try {
      await exportMissingAssetMarketDataCsv(filters);
    } catch (error) {
      toastApiError(error, "Missing asset market data export failed.");
    } finally {
      setIsExporting(false);
    }
  };

  return (
    <div className="space-y-4">
      <div className="flex flex-col gap-3 rounded-lg border bg-muted/10 p-3 sm:flex-row sm:items-center sm:justify-between">
        <div>
          <p className="font-medium text-sm">
            {formatPlainAmount(totalCount)} record{totalCount === 1 ? "" : "s"}
          </p>
          <p className="text-muted-foreground text-xs">
            Showing ISINs that need master-data completion.
          </p>
        </div>
        <Button
          type="button"
          variant="secondary"
          size="sm"
          disabled={isExporting}
          onClick={() => void exportFiltered()}
        >
          {isExporting ? "Exporting..." : "Export filtered"}
        </Button>
      </div>

      <DataTableShell
        table={table}
        columnCount={missingAssetMarketDataColumns.length}
        emptyMessage="No missing asset market data records match your filters."
        renderFilterCell={(header) =>
          renderFilterCell(header, filters, isinDraft, setIsinDraft, navigate)
        }
      />

      <DataTablePagination
        table={table}
        totalRows={totalCount}
        itemNoun="record"
        idPrefix="missing-asset-market-data"
        pageSizes={[DEFAULT_PAGE_SIZE, 50, 100]}
      />
    </div>
  );
}

function renderFilterCell(
  header: Header<MissingAssetMarketDataRow, unknown>,
  filters: MissingAssetMarketDataFilters,
  isinDraft: string,
  setIsinDraft: React.Dispatch<React.SetStateAction<string>>,
  navigate: (
    next: {
      isin?: string;
      baseAssetClass?: MissingAssetMarketDataFilters["baseAssetClass"];
      page?: number;
      pageSize?: number;
    },
    options?: { replace?: boolean },
  ) => void,
) {
  if (header.column.id === "isin") {
    return (
      <TableCell key={header.id} className="min-w-[210px] p-2">
        <Input
          value={isinDraft}
          onChange={(event) => setIsinDraft(event.target.value)}
          placeholder="Search ISIN..."
          className="h-9 bg-background font-mono text-xs"
        />
      </TableCell>
    );
  }

  if (header.column.id === "baseAssetClass") {
    return (
      <TableCell key={header.id} className="min-w-[190px] p-2">
        <Select
          value={filters.baseAssetClass}
          onValueChange={(value) =>
            navigate(
              {
                baseAssetClass: value as MissingAssetMarketDataFilters["baseAssetClass"],
                page: 1,
              },
              { replace: true },
            )
          }
        >
          <SelectTrigger className="h-9 bg-background text-xs">
            <SelectValue placeholder="Asset class" />
          </SelectTrigger>
          <SelectContent>
            {BASE_ASSET_CLASS_FILTER_OPTIONS.map((option) => (
              <SelectItem key={option.value} value={option.value}>
                {option.label}
              </SelectItem>
            ))}
          </SelectContent>
        </Select>
      </TableCell>
    );
  }

  return null;
}
