"use client";

import { toastApiError } from "@/lib/toast-api-error";
import * as React from "react";
import { Loader2, Pencil, Plus, Save, Search, Trash2 } from "lucide-react";
import { toast } from "sonner";

import { BankSetupTabs } from "@/app/customer/[tenant]/admin/_components/bank-setup-tabs";
import type {
  PortalParentBankRow,
  PortalStatusOption,
} from "@/app/customer/_lib/admin/parent-banks-server-api";
import { ACTIVE_INACTIVE_STATUS_OPTIONS, normalizeActiveStatus } from "@/config/status-codes";
import { customerCsrfHeader } from "@/lib/customer-csrf.client";
import { Badge } from "@/components/ui/badge";
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 {
  Sheet,
  SheetClose,
  SheetContent,
  SheetDescription,
  SheetFooter,
  SheetHeader,
  SheetTitle,
} from "@/components/ui/sheet";
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from "@/components/ui/table";

type ParentBanksPageClientProps = {
  tenant: string;
  initialItems: PortalParentBankRow[];
  initialStatusOptions: PortalStatusOption[];
  initialErrorMessage: string | null;
  catalogAvailable: boolean;
  canManage: boolean;
};

type FormState = {
  id: number;
  parentName: string;
  status: "A" | "I";
  sortOrder: string;
};

const DEFAULT_STATUS_OPTIONS: PortalStatusOption[] = ACTIVE_INACTIVE_STATUS_OPTIONS;

function emptyForm(): FormState {
  return {
    id: 0,
    parentName: "",
    status: "A",
    sortOrder: "0",
  };
}

function toForm(row: PortalParentBankRow): FormState {
  return {
    id: row.id,
    parentName: row.parentName,
    status: normalizeActiveStatus(row.status),
    sortOrder: String(row.sortOrder ?? 0),
  };
}

export function ParentBanksPageClient({
  tenant,
  initialItems,
  initialStatusOptions,
  initialErrorMessage,
  catalogAvailable,
  canManage,
}: ParentBanksPageClientProps) {
  const [rows, setRows] = React.useState(initialItems);
  const [search, setSearch] = React.useState("");
  const [sheetOpen, setSheetOpen] = React.useState(false);
  const [form, setForm] = React.useState<FormState>(emptyForm());
  const [isSaving, setIsSaving] = React.useState(false);
  const [deletingId, setDeletingId] = React.useState<number | null>(null);
  const statusOptions =
    initialStatusOptions.length > 0 ? initialStatusOptions : DEFAULT_STATUS_OPTIONS;

  const filtered = React.useMemo(() => {
    const q = search.trim().toLowerCase();
    if (!q) return rows;
    return rows.filter((row) =>
      [row.parentName, row.status, String(row.id), String(row.sortOrder)]
        .join(" ")
        .toLowerCase()
        .includes(q),
    );
  }, [rows, search]);

  const openCreate = () => {
    setForm(emptyForm());
    setSheetOpen(true);
  };

  const openEdit = (row: PortalParentBankRow) => {
    setForm(toForm(row));
    setSheetOpen(true);
  };

  const handleSave = async () => {
    if (!canManage) return;
    const parentName = form.parentName.trim();
    if (!parentName) {
      toast.error("Parent name is required.");
      return;
    }

    setIsSaving(true);
    try {
      const response = await fetch(`/customer/${tenant}/admin/parent-banks/save`, {
        method: "POST",
        headers: {
          Accept: "application/json",
          "Content-Type": "application/json",
          ...customerCsrfHeader(tenant),
        },
        body: JSON.stringify({
          id: form.id > 0 ? form.id : undefined,
          parentName,
          status: form.status,
          sortOrder: Number(form.sortOrder) || 0,
        }),
      });
      const data = (await response.json().catch(() => null)) as {
        status?: string;
        message?: string;
        item?: PortalParentBankRow | null;
      } | null;
      if (!response.ok || !data || data.status !== "success" || !data.item) {
        throw new Error(
          typeof data?.message === "string" ? data.message : "Failed to save parent bank.",
        );
      }

      const saved = data.item;
      setRows((prev) => {
        const exists = prev.some((row) => row.id === saved.id);
        const next = exists
          ? prev.map((row) => (row.id === saved.id ? saved : row))
          : [...prev, saved];
        return [...next].sort((a, b) => {
          if (a.sortOrder !== b.sortOrder) return b.sortOrder - a.sortOrder;
          return a.parentName.localeCompare(b.parentName);
        });
      });
      toast.success(data.message ?? "Parent bank saved successfully.");
      setSheetOpen(false);
    } catch (error) {
      toastApiError(error, "Failed to save parent bank.");
    } finally {
      setIsSaving(false);
    }
  };

  const handleDelete = async (row: PortalParentBankRow) => {
    if (!canManage) return;
    if (!window.confirm(`Delete parent bank “${row.parentName}”?`)) return;

    setDeletingId(row.id);
    try {
      const response = await fetch(`/customer/${tenant}/admin/parent-banks/delete`, {
        method: "POST",
        headers: {
          Accept: "application/json",
          "Content-Type": "application/json",
          ...customerCsrfHeader(tenant),
        },
        body: JSON.stringify({ id: row.id }),
      });
      const data = (await response.json().catch(() => null)) as {
        status?: string;
        message?: string;
      } | null;
      if (!response.ok || !data || data.status !== "success") {
        throw new Error(
          typeof data?.message === "string" ? data.message : "Failed to delete parent bank.",
        );
      }
      setRows((prev) => prev.filter((item) => item.id !== row.id));
      toast.success(data.message ?? "Parent bank deleted successfully.");
    } catch (error) {
      toastApiError(error, "Failed to delete parent bank.");
    } finally {
      setDeletingId(null);
    }
  };

  return (
    <>
      <div className="flex flex-col gap-4">
        <div className="flex flex-wrap items-start justify-between gap-3">
          <div>
            <h1 className="text-2xl tracking-tight">Parent Banks</h1>
            <p className="mt-1 text-sm text-muted-foreground">
              Catalog of parent banks used when linking customer bank accounts.
            </p>
          </div>
          {canManage && catalogAvailable ? (
            <Button type="button" onClick={openCreate}>
              <Plus className="size-4" />
              Create parent bank
            </Button>
          ) : null}
        </div>

        <BankSetupTabs tenant={tenant} active="parent-banks" />

        <div className="relative w-full max-w-sm">
          <Search className="pointer-events-none absolute left-2.5 top-1/2 size-4 -translate-y-1/2 text-muted-foreground" />
          <Input
            value={search}
            placeholder="Search parent banks"
            className="pl-8"
            onChange={(event) => setSearch(event.target.value)}
          />
        </div>

        {initialErrorMessage ? (
          <p className="rounded-md border border-destructive/30 bg-destructive/5 px-3 py-2 text-sm text-destructive">
            {initialErrorMessage}
          </p>
        ) : null}

        {!catalogAvailable && !initialErrorMessage ? (
          <p className="rounded-md border border-amber-500/30 bg-amber-500/5 px-3 py-2 text-sm text-amber-800 dark:text-amber-200">
            Parent banks catalog is not available on this environment.
          </p>
        ) : null}

        <div className="rounded-md border">
          <Table>
            <TableHeader>
              <TableRow className="bg-muted/40 hover:bg-muted/40">
                <TableHead className="px-3">Parent name</TableHead>
                <TableHead className="px-3">Status</TableHead>
                <TableHead className="px-3 text-center">Sort order</TableHead>
                <TableHead className="px-3 text-right">Actions</TableHead>
              </TableRow>
            </TableHeader>
            <TableBody>
              {filtered.length ? (
                filtered.map((row) => (
                  <TableRow key={row.id}>
                    <TableCell className="px-3 py-2.5 font-medium">{row.parentName}</TableCell>
                    <TableCell className="px-3 py-2.5">
                      <Badge variant={row.status === "A" ? "secondary" : "outline"}>
                        {row.status === "A" ? "Active" : "Inactive"}
                      </Badge>
                    </TableCell>
                    <TableCell className="px-3 py-2.5 text-center text-muted-foreground">
                      {row.sortOrder}
                    </TableCell>
                    <TableCell className="px-3 py-2.5 text-right">
                      <div className="inline-flex items-center gap-1">
                        <Button
                          type="button"
                          size="sm"
                          variant="outline"
                          onClick={() => openEdit(row)}
                        >
                          <Pencil className="size-3.5" />
                          {canManage ? "Edit" : "View"}
                        </Button>
                        {canManage ? (
                          <Button
                            type="button"
                            size="sm"
                            variant="ghost"
                            className="text-muted-foreground hover:text-destructive"
                            disabled={deletingId === row.id}
                            onClick={() => void handleDelete(row)}
                          >
                            {deletingId === row.id ? (
                              <Loader2 className="size-3.5 animate-spin" />
                            ) : (
                              <Trash2 className="size-3.5" />
                            )}
                          </Button>
                        ) : null}
                      </div>
                    </TableCell>
                  </TableRow>
                ))
              ) : (
                <TableRow>
                  <TableCell colSpan={4} className="h-24 text-center text-muted-foreground">
                    No parent banks found.
                  </TableCell>
                </TableRow>
              )}
            </TableBody>
          </Table>
        </div>
      </div>

      <Sheet open={sheetOpen} onOpenChange={setSheetOpen}>
        <SheetContent className="flex w-full flex-col gap-0 p-0 sm:max-w-md">
          <SheetHeader className="border-b px-6 py-4">
            <SheetTitle>{form.id > 0 ? "Edit parent bank" : "Create parent bank"}</SheetTitle>
            <SheetDescription>
              {canManage
                ? "Parent name, status, and sort order for the master catalog."
                : "Parent bank details."}
            </SheetDescription>
          </SheetHeader>

          <div className="flex flex-1 flex-col gap-4 overflow-y-auto px-6 py-4">
            <div className="flex flex-col gap-1.5">
              <Label htmlFor="parent-name">Parent name</Label>
              <Input
                id="parent-name"
                value={form.parentName}
                placeholder="e.g. HSBC Group"
                disabled={!canManage}
                onChange={(event) => setForm((prev) => ({ ...prev, parentName: event.target.value }))}
              />
            </div>
            <div className="grid gap-3 sm:grid-cols-2">
              <div className="flex flex-col gap-1.5">
                <Label htmlFor="parent-status">Status</Label>
                <Select
                  value={form.status}
                  disabled={!canManage}
                  onValueChange={(value) =>
                    setForm((prev) => ({ ...prev, status: normalizeActiveStatus(value) }))
                  }
                >
                  <SelectTrigger id="parent-status" className="w-full">
                    <SelectValue placeholder="Active" />
                  </SelectTrigger>
                  <SelectContent>
                    {statusOptions.map((option) => (
                      <SelectItem key={option.id} value={option.id}>
                        {option.name}
                      </SelectItem>
                    ))}
                  </SelectContent>
                </Select>
              </div>
              <div className="flex flex-col gap-1.5">
                <Label htmlFor="parent-sort">Sort order</Label>
                <Input
                  id="parent-sort"
                  type="number"
                  value={form.sortOrder}
                  disabled={!canManage}
                  onChange={(event) =>
                    setForm((prev) => ({ ...prev, sortOrder: event.target.value }))
                  }
                />
              </div>
            </div>
          </div>

          <SheetFooter className="flex-row justify-end gap-2 border-t px-6 py-4">
            <SheetClose asChild>
              <Button type="button" variant="outline" disabled={isSaving}>
                {canManage ? "Cancel" : "Close"}
              </Button>
            </SheetClose>
            {canManage ? (
              <Button type="button" onClick={() => void handleSave()} disabled={isSaving}>
                {isSaving ? (
                  <Loader2 className="size-4 animate-spin" />
                ) : (
                  <Save className="size-4" />
                )}
                Save
              </Button>
            ) : null}
          </SheetFooter>
        </SheetContent>
      </Sheet>
    </>
  );
}
