"use client";

import * as React from "react";
import { Building2, CircleCheck, Info, Landmark, Lock, Network, RotateCcw, Save, Wallet } from "lucide-react";
import type { LucideIcon } from "lucide-react";
import { toast } from "sonner";

import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group";
import { Skeleton } from "@/components/ui/skeleton";
import { cn } from "@/lib/utils";

import {
  dispatchReportBankModeChanged,
  normalizeReportBankFilterMode,
} from "@/app/customer/_lib/report-bank-mode-events";

import { loadReportBankSettings, saveReportBankSettings } from "../_lib/tenant-settings-api";
import type { ReportBankSettingsData } from "../_lib/tenant-settings-server-api";
import { errorMessageOr, toastApiError } from "@/lib/toast-api-error";

import { SettingsSection } from "./settings-section";

type ModePresentation = {
  label: string;
  help: string;
  icon: LucideIcon;
  /** Sample picker rows: `indent` marks a child account, `muted` one that is rolled up and not listed. */
  preview: { name: string; indent?: boolean; muted?: boolean }[];
};

const MODE_PRESENTATION: Record<string, ModePresentation> = {
  parent_only: {
    label: "Parent banks",
    help: "Show master parent banks. Child accounts roll up under their parent in reports.",
    icon: Building2,
    preview: [
      { name: "Bank A" },
      { name: "Account 1001", indent: true, muted: true },
      { name: "Account 1002", indent: true, muted: true },
      { name: "Bank B" },
    ],
  },
  children_only: {
    label: "Child accounts",
    help: "Show every child bank account in filters and reports, including accounts with no parent assigned.",
    icon: Network,
    preview: [
      { name: "Bank A · 1001" },
      { name: "Bank A · 1002" },
      { name: "Bank B · 2001" },
      { name: "Unassigned · 3001" },
    ],
  },
};

export function SettingsPanelReportBanks({ tenant }: { tenant: string }) {
  const [data, setData] = React.useState<ReportBankSettingsData | null>(null);
  const [mode, setMode] = React.useState("");
  const [loading, setLoading] = React.useState(true);
  const [saving, setSaving] = React.useState(false);
  const [error, setError] = React.useState<string | null>(null);

  React.useEffect(() => {
    let cancelled = false;
    void loadReportBankSettings(tenant)
      .then((result) => {
        if (cancelled) return;
        setData(result);
        setMode(normalizeReportBankFilterMode(result.report_bank_filter_mode));
      })
      .catch((loadError) => {
        if (!cancelled) setError(errorMessageOr(loadError, "Report Bank Settings could not be loaded."));
      })
      .finally(() => {
        if (!cancelled) setLoading(false);
      });
    return () => {
      cancelled = true;
    };
  }, [tenant]);

  async function save() {
    if (!mode) return;
    setSaving(true);
    try {
      const result = await saveReportBankSettings(tenant, mode);
      setData(result);
      const savedMode = normalizeReportBankFilterMode(result.report_bank_filter_mode);
      setMode(savedMode);
      dispatchReportBankModeChanged(savedMode);
      toast.success("Report Bank Settings saved");
    } catch (saveError) {
      toastApiError(saveError, "Settings could not be saved.");
    } finally {
      setSaving(false);
    }
  }

  if (loading) return <ReportBanksSkeleton />;
  if (error || !data) {
    return (
      <Alert variant="destructive">
        <Info />
        <AlertTitle>Report Bank Settings unavailable</AlertTitle>
        <AlertDescription>{error}</AlertDescription>
      </Alert>
    );
  }

  const modeOptions = Object.entries(data.modeOptions).filter(
    ([value]) => value !== "all" && value !== "parent_plus_children",
  );
  const savedMode = normalizeReportBankFilterMode(data.report_bank_filter_mode);
  const isDirty = mode !== savedMode;
  const savedLabel = MODE_PRESENTATION[savedMode]?.label ?? data.modeOptions[savedMode] ?? savedMode;

  return (
    <div className="space-y-8">
      <SettingsSection
        title="Consolidated Select Bank Mode"
        description="Controls which accounts appear in consolidated report bank pickers."
        action={
          <div className="flex flex-wrap items-center gap-2">
            {data.isReadOnly ? (
              <Badge variant="outline" className="gap-1 text-muted-foreground">
                <Lock /> Read only
              </Badge>
            ) : null}
            {savedLabel ? (
              <Badge variant="secondary" className="gap-1">
                <Landmark /> Active: {savedLabel}
              </Badge>
            ) : null}
          </div>
        }
      >
        <RadioGroup
          value={mode}
          onValueChange={setMode}
          disabled={data.isReadOnly}
          className="grid gap-4 sm:grid-cols-2"
        >
          {modeOptions.map(([value, apiLabel]) => {
            const presentation = MODE_PRESENTATION[value];
            const Icon = presentation?.icon ?? Wallet;
            const optionId = `report-bank-mode-${value}`;
            const selected = mode === value;
            return (
              <label
                key={value}
                htmlFor={optionId}
                className={cn(
                  "group relative flex cursor-pointer flex-col gap-4 rounded-xl border bg-card p-5 shadow-xs transition-all",
                  "hover:border-primary/40 hover:shadow-sm focus-within:ring-3 focus-within:ring-ring/50",
                  "has-[:disabled]:cursor-not-allowed has-[:disabled]:opacity-70 has-[:disabled]:hover:shadow-xs",
                  selected
                    ? "border-primary bg-primary/[0.03] ring-1 ring-primary dark:bg-primary/10"
                    : "border-border/80",
                )}
              >
                <RadioGroupItem id={optionId} value={value} className="sr-only" />

                <div className="flex items-start gap-3">
                  <span
                    className={cn(
                      "flex size-10 shrink-0 items-center justify-center rounded-lg transition-colors",
                      selected ? "bg-primary text-primary-foreground" : "bg-muted text-muted-foreground",
                    )}
                  >
                    <Icon className="size-5" />
                  </span>
                  <div className="min-w-0 flex-1 space-y-1">
                    <div className="flex flex-wrap items-center gap-2">
                      <span className="font-semibold text-sm">{presentation?.label ?? apiLabel}</span>
                      {value === savedMode ? (
                        <Badge variant="outline" className="h-4 px-1.5 text-[10px] text-muted-foreground">
                          Current
                        </Badge>
                      ) : null}
                    </div>
                    <p className="text-muted-foreground text-xs leading-relaxed">{presentation?.help ?? ""}</p>
                  </div>
                  <CircleCheck
                    aria-hidden
                    className={cn(
                      "size-5 shrink-0 transition-all",
                      selected ? "scale-100 text-primary opacity-100" : "scale-75 opacity-0",
                    )}
                  />
                </div>

                {presentation ? (
                  <div className="rounded-lg border border-dashed bg-muted/40 p-3">
                    <p className="mb-2 font-medium text-[10px] text-muted-foreground uppercase tracking-wider">
                      Bank picker preview
                    </p>
                    <ul className="space-y-1.5">
                      {presentation.preview.map((row) => (
                        <li
                          key={row.name}
                          className={cn(
                            "flex items-center gap-2 text-xs",
                            row.indent && "pl-5",
                            row.muted ? "text-muted-foreground/70 italic" : "text-foreground",
                          )}
                        >
                          <span
                            className={cn(
                              "size-1.5 shrink-0 rounded-full",
                              row.muted ? "bg-muted-foreground/40" : selected ? "bg-primary" : "bg-foreground/50",
                            )}
                          />
                          <span className="truncate">{row.name}</span>
                          {row.muted ? <span className="ml-auto text-[10px] not-italic">rolled up</span> : null}
                        </li>
                      ))}
                    </ul>
                  </div>
                ) : null}
              </label>
            );
          })}
        </RadioGroup>

        <div className="flex flex-col gap-3 rounded-xl border bg-muted/30 px-4 py-3 sm:flex-row sm:items-center sm:justify-between">
          <p className="flex items-start gap-2 text-muted-foreground text-xs leading-relaxed">
            <Info className="mt-0.5 size-3.5 shrink-0" />
            {isDirty
              ? "You have unsaved changes. Bank mode applies to every consolidated report bank picker for this tenant."
              : "Bank mode is saved for this tenant and applies to consolidated report bank pickers."}
          </p>
          {!data.isReadOnly ? (
            <div className="flex shrink-0 items-center gap-2 self-end sm:self-auto">
              {isDirty ? (
                <Button variant="ghost" size="sm" className="gap-1.5" disabled={saving} onClick={() => setMode(savedMode)}>
                  <RotateCcw className="size-3.5" /> Discard
                </Button>
              ) : null}
              <Button size="sm" className="gap-1.5" disabled={saving || !isDirty} onClick={() => void save()}>
                <Save className="size-3.5" /> {saving ? "Saving…" : "Save changes"}
              </Button>
            </div>
          ) : null}
        </div>
      </SettingsSection>
    </div>
  );
}

function ReportBanksSkeleton() {
  return (
    <div className="space-y-5" aria-busy="true" aria-label="Loading Report Bank Settings">
      <div className="space-y-2">
        <Skeleton className="h-5 w-64" />
        <Skeleton className="h-4 w-96 max-w-full" />
      </div>
      <div className="grid gap-4 sm:grid-cols-2">
        {[0, 1].map((key) => (
          <div key={key} className="space-y-4 rounded-xl border p-5">
            <div className="flex gap-3">
              <Skeleton className="size-10 rounded-lg" />
              <div className="flex-1 space-y-2">
                <Skeleton className="h-4 w-32" />
                <Skeleton className="h-3 w-full" />
              </div>
            </div>
            <Skeleton className="h-24 w-full rounded-lg" />
          </div>
        ))}
      </div>
      <Skeleton className="h-12 w-full rounded-xl" />
    </div>
  );
}
