"use client";

import { useRouter } from "next/navigation";
import * as React from "react";
import { toast } from "sonner";

import { ErrorBanner } from "@/components/shared/error-banner";
import { Button } from "@/components/ui/button";
import { toastApiError } from "@/lib/toast-api-error";

import { ApplyOptionsDialog } from "../../bulk-edit/_components/apply-options-dialog";
import { ApplyProgress } from "../../bulk-edit/_components/apply-progress";
import { PreviewTable } from "../../bulk-edit/_components/preview-table";
import {
  applyCorporateAction,
  cancelCorporateActionRun,
} from "../../bulk-edit/_lib/corporate-action-client-api";
import { countTrxTenants } from "../../bulk-edit/_lib/group-preview-rows";
import type {
  CorporateActionSummary,
  PreviewCounts,
  PreviewRow,
  RunStatus,
} from "../../bulk-edit/_lib/schema";
import { usePreviewSelection } from "../../bulk-edit/_lib/use-preview-selection";

type Props = {
  action: CorporateActionSummary;
  rows: PreviewRow[];
  counts: PreviewCounts;
};

/**
 * The corporate action's record list, in the same master-ISIN layout the
 * operator approved it in.
 *
 * While nothing has been written yet the list is live: transactions can be
 * ticked and unticked (a master ISIN ticks everything under it) and saved from
 * here, without a detour through the Bulk Edit form. Once any row has been
 * applied the same table becomes the read-only audit view.
 */
export function CorporateActionRowsTable({ action, rows, counts }: Props) {
  const router = useRouter();
  const isEditable = action.isEditable;

  const { selectedIds, toggleIds } = usePreviewSelection(rows);
  const [dialogOpen, setDialogOpen] = React.useState(false);
  const [isSaving, setIsSaving] = React.useState(false);
  const [run, setRun] = React.useState<RunStatus | null>(null);
  const [errorMessage, setErrorMessage] = React.useState<string | null>(null);

  const tenantCount = React.useMemo(() => countTrxTenants(rows), [rows]);

  const onApply = async (confirmIsin: string) => {
    setIsSaving(true);
    setErrorMessage(null);
    try {
      const result = await applyCorporateAction({
        actionId: action.id,
        selectedRowIds: [...selectedIds],
        underlyingIsin: action.underlyingIsin,
        confirmIsin,
      });

      setDialogOpen(false);

      if (result.run) {
        setRun(result.run);
        toast.success("Split queued.");
        return;
      }

      const failed = result.failed ?? 0;
      if (failed > 0) {
        setErrorMessage(result.errors?.slice(0, 5).join(" ") ?? null);
        toast.warning(`Applied ${result.applied ?? 0} record(s), ${failed} failed.`);
      } else {
        toast.success(`Applied ${result.applied ?? 0} record(s).`);
      }
      router.refresh();
    } catch (error) {
      toastApiError(error, "Could not apply the corporate action.");
    } finally {
      setIsSaving(false);
    }
  };

  const onCancelRun = async () => {
    setIsSaving(true);
    try {
      await cancelCorporateActionRun(action.id);
      setRun(null);
      toast.success("Queued run cancelled.");
      router.refresh();
    } catch (error) {
      toastApiError(error, "Could not cancel the queued run.");
    } finally {
      setIsSaving(false);
    }
  };

  const readOnly = !isEditable || run !== null;

  return (
    <div className="space-y-4">
      <ErrorBanner message={errorMessage ?? undefined} />

      {run ? (
        <ApplyProgress
          run={run}
          onCancel={onCancelRun}
          isCancelling={isSaving}
          onSettled={() => router.refresh()}
        />
      ) : null}

      <PreviewTable
        rows={rows}
        selectedIds={selectedIds}
        onToggleIds={toggleIds}
        readOnly={readOnly}
      />

      {!readOnly ? (
        <div className="flex items-center justify-between gap-4">
          <p className="text-muted-foreground text-sm">
            {selectedIds.size} of {rows.length} row(s) selected.
          </p>
          <Button
            type="button"
            onClick={() => setDialogOpen(true)}
            disabled={selectedIds.size === 0}
          >
            Save
          </Button>
        </div>
      ) : null}

      <ApplyOptionsDialog
        open={dialogOpen}
        onOpenChange={setDialogOpen}
        underlyingIsin={action.underlyingIsin}
        ratio={action.ratio}
        counts={counts}
        selectedCount={selectedIds.size}
        tenantCount={tenantCount}
        startDate={action.startDate}
        isSaving={isSaving}
        onApply={onApply}
      />
    </div>
  );
}
