"use client";

import * as React from "react";

import {
  getCoreRowModel,
  useReactTable,
  type Header,
  type PaginationState,
} from "@tanstack/react-table";
import { AlertTriangle } from "lucide-react";
import { useRouter } from "next/navigation";
import { toast } from "sonner";

import {
  DataTablePagination,
  DataTableShell,
  useDebouncedValue,
} from "@/app/dashboard/_components/data-table";
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
import { Button } from "@/components/ui/button";
import { Checkbox } from "@/components/ui/checkbox";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { TableCell } from "@/components/ui/table";

import { createStructureMasterColumns } from "./columns";
import {
  buildStructureMasterHref,
  DEFAULT_PAGE_SIZE,
  type StructureMasterRouteState,
} from "./constants";
import { StructureDetailsDialog } from "./structure-details-dialog";
import { formatPlainAmount } from "@/lib/format/numbers";
import type {
  StructureDuplicateStats,
  StructureMasterDetails,
  StructureMasterFilters,
  StructureMasterRow,
} from "./schema";

type Props = {
  data: StructureMasterRow[];
  filters: StructureMasterFilters;
  detailsById?: Record<number, StructureMasterDetails>;
  duplicateStats?: StructureDuplicateStats;
  totalCount: number;
  page: number;
  pageSize: number;
  pageCount: number;
};

const emptyDuplicateStats: StructureDuplicateStats = {
  couponDuplicates: 0,
  optionDuplicates: 0,
};

export function StructureMasterTable({
  data,
  filters,
  detailsById = {},
  duplicateStats = emptyDuplicateStats,
  totalCount,
  page,
  pageSize,
  pageCount,
}: Props) {
  const router = useRouter();
  const [isinDraft, setIsinDraft] = React.useState(filters.isin);
  const [nameDraft, setNameDraft] = React.useState(filters.name);
  const debouncedIsin = useDebouncedValue(isinDraft);
  const debouncedName = useDebouncedValue(nameDraft);
  const [detailsOpen, setDetailsOpen] = React.useState(false);
  const [selectedDetails, setSelectedDetails] = React.useState<{
    isin: string;
    id: number;
  } | null>(null);

  const navigate = React.useCallback(
    (
      next: Partial<StructureMasterRouteState>,
      options?: { replace?: boolean },
    ) => {
      const href = buildStructureMasterHref({
        isin: next.isin ?? filters.isin,
        name: next.name ?? filters.name,
        duplicateCouponDate:
          next.duplicateCouponDate ?? filters.duplicateCouponDate,
        duplicateObservationDate:
          next.duplicateObservationDate ?? filters.duplicateObservationDate,
        page: next.page ?? page,
        pageSize: next.pageSize ?? pageSize,
      });

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

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

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

  React.useEffect(() => {
    setNameDraft(filters.name);
  }, [filters.name]);

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

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

  React.useEffect(() => {
    const normalizedName = debouncedName.trim();
    if (normalizedName === filters.name) {
      return;
    }

    navigate({ name: normalizedName, page: 1 }, { replace: true });
  }, [debouncedName, filters.name, navigate]);

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

  const columns = React.useMemo(
    () =>
      createStructureMasterColumns({
        onViewDetails: (row) => {
          setSelectedDetails({ isin: row.isin, id: row.id });
          setDetailsOpen(true);
        },
      }),
    [],
  );

  const table = useReactTable({
    data,
    columns,
    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) => String(row.id),
  });

  const details =
    selectedDetails !== null
      ? detailsById[selectedDetails.id] ?? null
      : null;

  const showDuplicateAlert =
    duplicateStats.couponDuplicates > 0 || duplicateStats.optionDuplicates > 0;

  return (
    <div className="space-y-4">
      <div className="flex flex-wrap items-center gap-4 rounded-lg border bg-muted/20 px-4 py-3">
        <div className="flex items-center gap-2">
          <Checkbox
            id="duplicate_observation_date"
            checked={filters.duplicateObservationDate}
            onCheckedChange={(checked) =>
              navigate({
                duplicateObservationDate: checked === true,
                page: 1,
              })
            }
          />
          <Label htmlFor="duplicate_observation_date" className="font-normal text-sm">
            Duplicate observation date entry
          </Label>
        </div>
        <div className="flex items-center gap-2">
          <Checkbox
            id="duplicate_coupon_date"
            checked={filters.duplicateCouponDate}
            onCheckedChange={(checked) =>
              navigate({
                duplicateCouponDate: checked === true,
                page: 1,
              })
            }
          />
          <Label htmlFor="duplicate_coupon_date" className="font-normal text-sm">
            Duplicate coupon date entry
          </Label>
        </div>
      </div>

      {showDuplicateAlert ? (
        <Alert className="border-amber-300 bg-amber-50/90">
          <AlertTriangle className="size-4 text-amber-700" />
          <AlertTitle className="text-amber-900">Duplicate records alert</AlertTitle>
          <AlertDescription className="text-amber-900/90">
            <ul className="mt-1 list-disc space-y-0.5 pl-5 text-sm">
              {duplicateStats.couponDuplicates > 0 ? (
                <li>
                  Coupon duplicates: <strong>{duplicateStats.couponDuplicates}</strong>{" "}
                  found
                </li>
              ) : null}
              {duplicateStats.optionDuplicates > 0 ? (
                <li>
                  Option duplicates: <strong>{duplicateStats.optionDuplicates}</strong>{" "}
                  found
                </li>
              ) : null}
            </ul>
          </AlertDescription>
        </Alert>
      ) : null}

      <p className="text-muted-foreground text-sm">
        {formatPlainAmount(totalCount)} structure{totalCount === 1 ? "" : "s"}
      </p>

      <DataTableShell
        table={table}
        columnCount={columns.length}
        emptyMessage="No records found."
        renderFilterCell={(header) =>
          renderFilterCell(header, isinDraft, nameDraft, setIsinDraft, setNameDraft)
        }
      />

      <DataTablePagination
        table={table}
        totalRows={totalCount}
        itemNoun="structure"
        idPrefix="structure-master"
        pageSizes={[25, DEFAULT_PAGE_SIZE, 100]}
      />

      <div className="flex justify-end border-t pt-4">
        <Button
          type="button"
          onClick={() => toast.success("Structure priority updated")}
        >
          Update priority
        </Button>
      </div>

      <StructureDetailsDialog
        open={detailsOpen}
        onOpenChange={setDetailsOpen}
        isin={selectedDetails?.isin}
        details={details}
      />
    </div>
  );
}

function renderFilterCell(
  header: Header<StructureMasterRow, unknown>,
  isinDraft: string,
  nameDraft: string,
  setIsinDraft: React.Dispatch<React.SetStateAction<string>>,
  setNameDraft: React.Dispatch<React.SetStateAction<string>>,
) {
  if (header.column.id === "isin") {
    return (
      <TableCell key={header.id} className="p-2">
        <Input
          value={isinDraft}
          onChange={(event) => setIsinDraft(event.target.value)}
          placeholder="Search ISIN"
          className="h-8 bg-background font-mono text-xs"
        />
      </TableCell>
    );
  }

  if (header.column.id === "name") {
    return (
      <TableCell key={header.id} className="p-2">
        <Input
          value={nameDraft}
          onChange={(event) => setNameDraft(event.target.value)}
          placeholder="Name"
          className="h-8 bg-background text-xs"
        />
      </TableCell>
    );
  }

  return null;
}
