"use client";

import { mutationCsrfHeaders } from "@/lib/mutation-csrf.client";
import { toastApiError } from "@/lib/toast-api-error";
import { Check, ChevronLeft, ChevronRight, FileText, Loader2 } from "lucide-react";
import { useRouter } from "next/navigation";
import * as React from "react";
import { toast } from "sonner";

import { DatePicker, TimePicker } from "@/components/date-range-picker";
import { formDatePickerClass } from "@/components/form/common/form-layout";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select";
import { Textarea } from "@/components/ui/textarea";
import {
  countSectionFill,
  getColumnsBySection,
  mergeSelectOptions,
  ORDER_BLOTTER_SECTION_ORDER,
  ORDER_BLOTTER_SECTION_TITLES,
  blotterDateFromInputValue,
  blotterDateToInputValue,
  blotterTimeFromInputValue,
  blotterTimeToInputValue,
  formatDecimalForDisplay,
  registryInputVariantForKey,
  registrySelectOptionsForKey,
  type OrderBlotterColumnDef,
  type OrderBlotterSectionId,
} from "@/lib/order-blotter/column-registry";
import { cn } from "@/lib/utils";

import type { OrderBlotterDetail, OrderBlotterFieldData } from "./detail-types";
import {
  OrderBlotterDocumentsPanel,
  type OcrApiResponse,
} from "./order-blotter-documents-panel";

type OrderBlotterStepFormProps = {
  detail: OrderBlotterDetail;
  isCreate?: boolean;
  savePath?: string;
  ocrPath?: string;
  redirectBase?: string;
  prefilledFromTransaction?: boolean;
  transactionId?: number;
};

type WizardView = "documents" | "form";

/** Shorter labels for the left step rail (full titles stay on the form panel). */
function sectionNavLabels(advisorName: string): Record<OrderBlotterSectionId, string> {
  const advisor = advisorName.trim() || "Advisor";
  return {
    generic_details: "Generic details",
    trade_details: "Trade details",
    order_details_sent_to_client: "Order details to client",
    client_confirmation: "Client confirmation",
    trade_notified_custodian_bank: "Custodian notification",
    custodian_confirmation_to_ucap: `Custodian confirmation to ${advisor}`,
    ucap_trade_confirmation_to_client: `${advisor} confirmation to client`,
    suitability_assessment: "Suitability assessment",
    revenue_recognition: "Revenue recognition",
    internal_sign_off: "Internal sign-off",
    escalation: "Escalations",
    compliance_review: "Compliance review",
  };
}

function sectionPanelTitle(
  sectionId: OrderBlotterSectionId,
  advisorName: string,
  sectionTitles?: Partial<Record<string, string>>,
): string {
  const fromApi = sectionTitles?.[sectionId]?.trim();
  if (fromApi) return fromApi;

  const advisor = (advisorName.trim() || "Advisor").toUpperCase();
  if (sectionId === "custodian_confirmation_to_ucap") {
    return `CUSTODIAN TRADE CONFIRMATION TO ${advisor}`;
  }
  if (sectionId === "ucap_trade_confirmation_to_client") {
    return `${advisor} TRADE CONFIRMATION TO CLIENT`;
  }
  return ORDER_BLOTTER_SECTION_TITLES[sectionId];
}

export function OrderBlotterStepForm({
  detail,
  isCreate = false,
  savePath = "/dashboard/order-blotter/save",
  ocrPath = "/dashboard/order-blotter/ocr",
  redirectBase = "/dashboard/order-blotter",
  prefilledFromTransaction = false,
  transactionId,
}: OrderBlotterStepFormProps) {
  const router = useRouter();
  const columnsBySection = React.useMemo(() => getColumnsBySection(), []);
  const selectOptions = React.useMemo(
    () => mergeSelectOptions(detail.selectOptions),
    [detail.selectOptions],
  );
  const advisorLabel = detail.advisorLabel?.trim() || detail.portfolioLabel?.trim() || "Advisor";
  const navLabels = React.useMemo(() => sectionNavLabels(advisorLabel), [advisorLabel]);
  const [fields, setFields] = React.useState<OrderBlotterFieldData>(() =>
    normalizeSelectFieldValues(detail.fields, selectOptions),
  );
  const [activeStep, setActiveStep] = React.useState(0);
  const [activeView, setActiveView] = React.useState<WizardView>("form");
  const [saving, setSaving] = React.useState(false);
  const [docFiles, setDocFiles] = React.useState<File[]>([]);
  const [ocrResult, setOcrResult] = React.useState<OcrApiResponse | null>(null);

  const resolvedTransactionId =
    transactionId ?? (detail.transactionId != null && detail.transactionId > 0 ? detail.transactionId : null);

  const sectionSteps = ORDER_BLOTTER_SECTION_ORDER.map((sectionId) => {
    const columns = columnsBySection[sectionId] ?? [];
    const fill = countSectionFill(columns, fields);
    return {
      id: sectionId,
      ...fill,
      complete: fill.total > 0 && fill.filled === fill.total,
    };
  });

  const totalFields = sectionSteps.reduce((sum, step) => sum + step.total, 0);
  const filledFields = sectionSteps.reduce((sum, step) => sum + step.filled, 0);
  const overallPercent = totalFields > 0 ? Math.round((filledFields / totalFields) * 100) : 0;

  const activeSectionId = sectionSteps[activeStep]?.id ?? ORDER_BLOTTER_SECTION_ORDER[0];
  const activeColumns = columnsBySection[activeSectionId] ?? [];

  const onFieldChange = (key: string, value: string) => {
    setFields((prev) => ({ ...prev, [key]: value }));
  };

  const goToStep = (index: number) => {
    setActiveView("form");
    setActiveStep(Math.max(0, Math.min(index, sectionSteps.length - 1)));
  };

  const jumpToSection = (sectionId: OrderBlotterSectionId) => {
    const index = ORDER_BLOTTER_SECTION_ORDER.indexOf(sectionId);
    if (index >= 0) {
      goToStep(index);
    } else {
      setActiveView("form");
    }
  };

  const applyOcrFields = (incoming: Record<string, string>, overwrite: boolean): number => {
    let applied = 0;
    const nextFields: OrderBlotterFieldData = { ...fields };
    for (const [key, value] of Object.entries(incoming)) {
      const trimmed = String(value ?? "").trim();
      if (!trimmed) continue;
      const existing = String(nextFields[key] ?? "").trim();
      if (!overwrite && existing) continue;
      nextFields[key] = trimmed;
      applied += 1;
    }
    setFields(normalizeSelectFieldValues(nextFields, selectOptions));
    return applied;
  };

  const handleSave = async () => {
    setSaving(true);
    try {
      const response = await fetch(savePath, {
        method: "POST",
        credentials: "same-origin",
        headers: {
          "Content-Type": "application/json",
          Accept: "application/json",
          ...mutationCsrfHeaders(savePath),
        },
        body: JSON.stringify({
          id: isCreate ? null : detail.id,
          ref: detail.ref ?? null,
          OrderBlotterData: fields,
          OrderBlotter: {
            transaction_id: resolvedTransactionId,
            transaction_corporate_db: detail.portfolio ?? null,
          },
        }),
      });
      const payload = (await response.json().catch(() => null)) as {
        status?: string;
        message?: string;
        id?: number;
        ref?: string;
      } | null;
      if (!response.ok || payload?.status === "error") {
        throw new Error(payload?.message || "Save failed");
      }
      toast.success(isCreate ? "Order blotter created" : "Order blotter saved");
      const nextId = payload?.id ?? detail.id;
      const refQs = payload?.ref ? `&ref=${encodeURIComponent(payload.ref)}` : "";
      router.push(`${redirectBase}/${nextId}?action=update${refQs}`);
      router.refresh();
    } catch (error) {
      toastApiError(error, "Save failed");
    } finally {
      setSaving(false);
    }
  };

  return (
    <div className="flex flex-col gap-3">
      <div className="flex flex-wrap items-center gap-x-3 gap-y-1 rounded-md border border-border bg-muted/50 px-3 py-1.5 text-[11px] text-muted-foreground">
        <span className="min-w-0 truncate">
          <span className="font-semibold uppercase tracking-wide text-muted-foreground">Portfolio</span>
          <span className="mx-1.5 text-border">·</span>
          <span className="text-foreground">
            {detail.portfolioLabel ?? "Current corporate DB"}
          </span>
        </span>
        {resolvedTransactionId ? (
          <>
            <span className="hidden text-border sm:inline" aria-hidden>
              |
            </span>
            <span className="shrink-0">
              <span className="font-semibold uppercase tracking-wide text-muted-foreground">Txn</span>
              <span className="mx-1.5 text-border">·</span>
              <span className="font-mono text-foreground">{resolvedTransactionId}</span>
              {prefilledFromTransaction ? (
                <span className="ml-1.5 text-muted-foreground">prefilled</span>
              ) : null}
            </span>
          </>
        ) : null}
      </div>

      <div className="overflow-hidden rounded-lg border border-border bg-card shadow-sm">
        <div className="flex items-center justify-between gap-2 border-b border-border px-3 py-2">
          <div className="flex items-center gap-2">
            <span className="flex size-7 items-center justify-center rounded-md bg-violet-500/10 text-violet-700 dark:text-violet-400">
              <FileText className="size-3.5" />
            </span>
            <div className="hidden items-center gap-0.5 sm:flex">
              <TabButton
                active={activeView === "documents"}
                onClick={() => setActiveView("documents")}
              >
                Documents
              </TabButton>
              <TabButton active={activeView === "form"} onClick={() => setActiveView("form")}>
                Form steps
              </TabButton>
            </div>
          </div>
          <Button
            type="button"
            size="sm"
            className="h-8 px-3 text-xs"
            onClick={() => void handleSave()}
            disabled={saving}
          >
            {saving ? (
              <>
                <Loader2 className="mr-1.5 size-3.5 animate-spin" />
                Saving…
              </>
            ) : isCreate ? (
              "Save new blotter"
            ) : (
              "Save changes"
            )}
          </Button>
        </div>

        <div className="flex flex-col lg:flex-row lg:items-stretch">
          <aside
            className={cn(
              "border-b border-border bg-muted/50 lg:border-b-0",
              activeView === "documents"
                ? "lg:hidden"
                : "lg:w-64 lg:shrink-0 lg:border-r xl:w-72",
            )}
          >
            <div className="flex gap-1 border-b border-border p-2 sm:hidden">
              <TabButton
                active={activeView === "documents"}
                onClick={() => setActiveView("documents")}
                className="flex-1 justify-center text-xs"
              >
                Documents
              </TabButton>
              <TabButton
                active={activeView === "form"}
                onClick={() => setActiveView("form")}
                className="flex-1 justify-center text-xs"
              >
                Form steps
              </TabButton>
            </div>

            {activeView === "form" ? (
              <>
                <div className="border-b border-border px-3 py-2">
                  <div className="flex items-center justify-between text-[11px] text-muted-foreground">
                    <span>Overall progress</span>
                    <span className="font-semibold tabular-nums text-foreground">
                      {overallPercent}%
                    </span>
                  </div>
                  <div className="mt-1.5 h-1 overflow-hidden rounded-full bg-muted">
                    <div
                      className="h-full rounded-full bg-emerald-500 transition-all duration-300"
                      style={{ width: `${overallPercent}%` }}
                    />
                  </div>
                </div>

                <nav aria-label="Form steps" className="max-h-[32rem] overflow-y-auto p-2">
                  <ol className="relative space-y-0.5">
                    <span
                      aria-hidden
                      className="absolute top-3 bottom-3 left-[13px] w-px bg-border"
                    />
                    {sectionSteps.map((step, index) => {
                      const isActive = activeStep === index;
                      return (
                        <li key={step.id} className="relative">
                          <button
                            type="button"
                            className={cn(
                              "flex w-full items-center gap-2 rounded-md px-1.5 py-1.5 text-left transition-colors",
                              isActive
                                ? "bg-sky-500/10 ring-1 ring-sky-500/30 dark:bg-sky-500/15 dark:ring-sky-400/30"
                                : "hover:bg-accent",
                            )}
                            onClick={() => goToStep(index)}
                          >
                            <span
                              className={cn(
                                "relative z-10 flex size-[26px] shrink-0 items-center justify-center rounded-full border text-[11px] font-bold leading-none",
                                step.complete
                                  ? "border-emerald-600 bg-emerald-600 text-white"
                                  : isActive
                                    ? "border-primary bg-primary text-primary-foreground"
                                    : "border-border bg-card text-muted-foreground",
                              )}
                            >
                              {step.complete ? (
                                <Check className="size-3" strokeWidth={3} />
                              ) : (
                                index + 1
                              )}
                            </span>
                            <span
                              className={cn(
                                "min-w-0 flex-1 text-[10px] font-semibold uppercase leading-tight tracking-wide",
                                isActive ? "text-foreground" : "text-foreground/80",
                              )}
                            >
                              {navLabels[step.id]}
                            </span>
                            <span
                              className={cn(
                                "shrink-0 rounded px-1.5 py-0.5 text-[10px] font-medium tabular-nums",
                                step.complete
                                  ? "bg-emerald-500/10 text-emerald-700 dark:text-emerald-400"
                                  : step.filled > 0
                                    ? "bg-amber-500/10 text-amber-700 dark:text-amber-400"
                                    : "bg-muted text-muted-foreground",
                              )}
                            >
                              {step.filled}/{step.total}
                            </span>
                          </button>
                        </li>
                      );
                    })}
                  </ol>
                </nav>
              </>
            ) : null}
          </aside>

          <div className="flex min-h-0 min-w-0 flex-1 flex-col bg-card">
            <div
              className={cn(
                "flex-1 p-4 md:p-6",
                activeView === "documents" && "min-h-[28rem] lg:min-h-[32rem]",
                activeView === "form" && "min-h-[24rem] lg:min-h-[28rem]",
              )}
            >
              {activeView === "documents" ? (
                <OrderBlotterDocumentsPanel
                  ocrPath={ocrPath}
                  files={docFiles}
                  onFilesChange={setDocFiles}
                  result={ocrResult}
                  onResultChange={setOcrResult}
                  onApplyFields={applyOcrFields}
                  onJumpToSection={jumpToSection}
                />
              ) : (
                <SectionFields
                  sectionId={activeSectionId}
                  columns={activeColumns}
                  fields={fields}
                  onFieldChange={onFieldChange}
                  selectOptions={selectOptions}
                  advisorLabel={advisorLabel}
                  sectionTitles={detail.sectionTitles}
                />
              )}
            </div>

            {activeView === "form" ? (
              <div className="mt-auto flex shrink-0 items-center justify-between border-t border-border bg-muted/60 px-3 py-2.5 md:px-4">
                <Button
                  type="button"
                  variant="outline"
                  size="sm"
                  className="h-7 px-2 text-xs"
                  disabled={activeStep <= 0}
                  onClick={() => goToStep(activeStep - 1)}
                >
                  <ChevronLeft className="mr-0.5 size-3.5" />
                  Previous
                </Button>
                <span className="text-[11px] text-muted-foreground">
                  Step {activeStep + 1} of {sectionSteps.length}
                </span>
                <Button
                  type="button"
                  variant="outline"
                  size="sm"
                  className="h-7 px-2 text-xs"
                  disabled={activeStep >= sectionSteps.length - 1}
                  onClick={() => goToStep(activeStep + 1)}
                >
                  Next
                  <ChevronRight className="ml-0.5 size-3.5" />
                </Button>
              </div>
            ) : null}
          </div>
        </div>
      </div>
    </div>
  );
}

function TabButton({
  active,
  onClick,
  children,
  className,
}: {
  active: boolean;
  onClick: () => void;
  children: React.ReactNode;
  className?: string;
}) {
  return (
    <button
      type="button"
      onClick={onClick}
      className={cn(
        "rounded-md px-2.5 py-1 text-xs font-medium transition-colors",
        active ? "bg-primary text-primary-foreground" : "text-muted-foreground hover:bg-muted",
        className,
      )}
    >
      {children}
    </button>
  );
}

function SectionFields({
  sectionId,
  columns,
  fields,
  onFieldChange,
  selectOptions,
  advisorLabel,
  sectionTitles,
}: {
  sectionId: OrderBlotterSectionId;
  columns: OrderBlotterColumnDef[];
  fields: OrderBlotterFieldData;
  onFieldChange: (key: string, value: string) => void;
  selectOptions: Record<string, Record<string, string>>;
  advisorLabel: string;
  sectionTitles?: Partial<Record<string, string>>;
}) {
  return (
    <div className="space-y-2.5">
      <h3 className="border-b border-border pb-1.5 text-xs font-bold uppercase tracking-wide text-foreground">
        {sectionPanelTitle(sectionId, advisorLabel, sectionTitles)}
      </h3>
      <div className="grid gap-x-3 gap-y-2 sm:grid-cols-2 xl:grid-cols-3">
        {columns.map((column) => (
          <FieldControl
            key={column.key}
            column={column}
            value={fields[column.key] ?? ""}
            onChange={(value) => onFieldChange(column.key, value)}
            selectOptions={selectOptions}
          />
        ))}
      </div>
    </div>
  );
}

function FieldControl({
  column,
  value,
  onChange,
  selectOptions,
}: {
  column: OrderBlotterColumnDef;
  value: string;
  onChange: (value: string) => void;
  selectOptions: Record<string, Record<string, string>>;
}) {
  const selectOptionsForKey =
    selectOptions[column.key] ?? registrySelectOptionsForKey(column.key);
  const fullWidth = column.type === "textarea" || column.fullWidth;
  const variant = registryInputVariantForKey(column.key);
  const isLongText = column.key === "action_taken_rationale" || column.key === "suitability_assessment_field";

  return (
    <div className={cn("space-y-0.5", fullWidth && "sm:col-span-2 xl:col-span-3")}>
      <Label
        htmlFor={`ob-field-${column.key}`}
        className="text-[10px] font-semibold uppercase tracking-wide text-muted-foreground"
      >
        {column.label}
      </Label>
      {selectOptionsForKey ? (
        <Select value={value || undefined} onValueChange={onChange}>
          <SelectTrigger
            id={`ob-field-${column.key}`}
            className="h-8 w-full border-input bg-muted px-2.5 text-sm shadow-none"
          >
            <SelectValue placeholder="Select…" />
          </SelectTrigger>
          <SelectContent>
            {Object.entries(selectOptionsForKey).map(([optionKey, optionLabel]) => (
              <SelectItem key={optionKey} value={String(optionKey)}>
                {optionLabel}
              </SelectItem>
            ))}
          </SelectContent>
        </Select>
      ) : column.type === "textarea" ? (
        <Textarea
          id={`ob-field-${column.key}`}
          value={value}
          rows={isLongText ? 6 : 3}
          className="min-h-0 border-input bg-muted px-2.5 py-1.5 text-sm shadow-none"
          onChange={(event) => onChange(event.target.value)}
        />
      ) : variant === "date" ? (
        <DatePicker
          id={`ob-field-${column.key}`}
          value={blotterDateToInputValue(value) || value}
          placeholder="Select date"
          align="start"
          className={cn(formDatePickerClass, "border-input bg-muted shadow-none")}
          onChange={(next) => onChange(blotterDateFromInputValue(next))}
        />
      ) : variant === "time" ? (
        <TimePicker
          id={`ob-field-${column.key}`}
          value={blotterTimeToInputValue(value)}
          placeholder="Select time"
          align="start"
          className={cn(formDatePickerClass, "border-input bg-muted shadow-none")}
          onChange={(next) => onChange(blotterTimeFromInputValue(next))}
        />
      ) : variant === "decimal" ? (
        <Input
          id={`ob-field-${column.key}`}
          inputMode="decimal"
          value={value}
          className="h-8 border-input bg-muted px-2.5 text-sm shadow-none"
          onChange={(event) => onChange(event.target.value)}
          onBlur={() => {
            const formatted = formatDecimalForDisplay(value, column.key);
            if (formatted && formatted !== value) onChange(formatted);
          }}
        />
      ) : (
        <Input
          id={`ob-field-${column.key}`}
          value={value}
          className="h-8 border-input bg-muted px-2.5 text-sm shadow-none"
          onChange={(event) => onChange(event.target.value)}
        />
      )}
    </div>
  );
}

function normalizeSelectFieldValues(
  fields: OrderBlotterFieldData,
  selectOptions: Record<string, Record<string, string>>,
): OrderBlotterFieldData {
  const next: OrderBlotterFieldData = { ...fields };

  for (const [fieldKey, opts] of Object.entries(selectOptions)) {
    const raw = next[fieldKey];
    if (raw == null) continue;
    const stored = String(raw).trim();
    if (!stored) continue;

    if (Object.prototype.hasOwnProperty.call(opts, stored)) continue;

    const storedLc = stored.toLowerCase();
    for (const [optKey, optLabel] of Object.entries(opts)) {
      if (String(optLabel).trim().toLowerCase() === storedLc) {
        next[fieldKey] = String(optKey);
        break;
      }
    }
  }

  return next;
}
