"use client";
import { useEffect, useState } from "react";
import Image from "next/image";
import { CreditCard, Plus } from "lucide-react";
import {
  Panel,
  PreviewNotice,
  StatusBadge,
} from "@/components/shared/page";
import { Field, SelectField } from "@/components/shared/field";
import { Button } from "@/components/ui/button";
import { Switch } from "@/components/ui/switch";
import {
  Dialog,
  DialogContent,
  DialogHeader,
  DialogTitle,
  DialogDescription,
  DialogFooter,
} from "@/components/ui/dialog";
import { usePreviewRole } from "@/components/layout/preview-context";
import { useDashboardAuth } from "@/components/layout/dashboard-auth-context";
import { canManage } from "@/lib/preview";
import {
  createPaymentAccount,
  disablePaymentChannel,
  enablePaymentChannel,
  getAccountChannels,
  getGatewayChannels,
  getPaymentGateways,
  getPaymentAccounts,
  toCreateAccountPayload,
  toUpdateAccountPayload,
  updatePaymentAccount,
} from "./api-client";
import {
  paymentChannelTypeLabel,
  validateGatewayAccount,
  type GatewayAccount,
  type GatewayAccountDraft,
  type PaymentChannel,
  type PaymentGateway,
} from "./model";
const redirectFields = [
  { key: "successUrl", label: "Success URL" },
  { key: "failureUrl", label: "Failure URL" },
  { key: "pendingUrl", label: "Pending URL" },
  { key: "cancelUrl", label: "Cancel URL" },
] as const;
export function PaymentConfiguration({
  previewState,
}: {
  previewState: "populated" | "empty" | "error";
}) {
  const { apiConfigured } = useDashboardAuth();
  const manage = canManage(usePreviewRole());
  const [accounts, setAccounts] = useState<GatewayAccount[]>([]);
  const [paymentGateways, setPaymentGateways] = useState<PaymentGateway[]>([]);
  const [gatewayCatalogState, setGatewayCatalogState] = useState<
    "idle" | "loaded" | "failed"
  >("idle");
  const [gatewayCatalogError, setGatewayCatalogError] = useState("");
  const [gatewayCatalogReloadKey, setGatewayCatalogReloadKey] = useState(0);
  const [selectedId, setSelectedId] = useState("");
  const [remoteChannels, setRemoteChannels] = useState<PaymentChannel[]>([]);
  const [draft, setDraft] = useState<GatewayAccountDraft | null>(null);
  const [error, setError] = useState("");
  const [pageError, setPageError] = useState("");
  const [notice, setNotice] = useState("");
  const [loading, setLoading] = useState(apiConfigured);
  const [accountLoadFailed, setAccountLoadFailed] = useState(false);
  const [accountReloadKey, setAccountReloadKey] = useState(0);
  const [channelReloadKey, setChannelReloadKey] = useState(0);
  const [channelLoadState, setChannelLoadState] = useState<{
    accountId: string;
    status: "loaded" | "failed";
  } | null>(null);
  const [gatewayChannels, setGatewayChannels] = useState<PaymentChannel[]>([]);
  const [gatewayChannelLoadState, setGatewayChannelLoadState] = useState<{
    gatewayId: string;
    status: "loading" | "loaded" | "failed";
  } | null>(null);
  const [gatewayChannelError, setGatewayChannelError] = useState("");
  const [gatewayChannelReloadKey, setGatewayChannelReloadKey] = useState(0);
  const [saving, setSaving] = useState(false);
  const [accountBusyId, setAccountBusyId] = useState("");
  const [pendingChannelIds, setPendingChannelIds] = useState<string[]>([]);
  const [deactivating, setDeactivating] = useState<GatewayAccount | null>(null);
  const selected = accounts.find((account) => account.id === selectedId);
  const draftAccount = draft
    ? accounts.find((account) => account.id === draft.id)
    : undefined;
  const availableGateways = paymentGateways.filter((gateway) => gateway.active);
  const selectedGatewayId = selected?.gatewayId;
  const selectedGatewayName = selected?.gateway;
  const channelsLoading =
    apiConfigured &&
    !!selectedId &&
    channelLoadState?.accountId !== selectedId;
  const hasLoadedChannels =
    channelLoadState?.accountId === selectedId &&
    channelLoadState.status === "loaded";
  const channels = hasLoadedChannels ? remoteChannels : [];
  const gatewayChannelsLoading =
    apiConfigured &&
    !!selectedGatewayId &&
    (gatewayChannelLoadState?.gatewayId !== selectedGatewayId ||
      gatewayChannelLoadState.status === "loading");
  const hasLoadedGatewayChannels =
    !!selectedGatewayId &&
    gatewayChannelLoadState?.gatewayId === selectedGatewayId &&
    gatewayChannelLoadState?.status === "loaded";
  const connectedChannelIds = new Set(channels.map((channel) => channel.id));
  const allChannels = hasLoadedGatewayChannels ? gatewayChannels : [];
  const previewAccountEmpty = !apiConfigured && previewState === "empty";
  const previewAccountFailure = !apiConfigured && previewState === "error";
  const accountListFailed = accountLoadFailed || previewAccountFailure;
  const showAccountSetup =
    !loading &&
    accounts.length === 0 &&
    !accountListFailed &&
    (apiConfigured || previewAccountEmpty);
  const channelTypes = [...new Set(allChannels.map((channel) => channel.type))].sort(
    (a, b) => paymentChannelTypeLabel(a).localeCompare(paymentChannelTypeLabel(b)),
  );

  useEffect(() => {
    if (!apiConfigured) return;
    let current = true;
    async function load() {
      setLoading(true);
      setPageError("");
      setAccountLoadFailed(false);
      try {
        const accountRows = await getPaymentAccounts();
        if (!current) return;
        setAccounts(accountRows);
        setSelectedId(accountRows[0]?.id ?? "");
      } catch (err) {
        if (!current) return;
        setAccounts([]);
        setSelectedId("");
        setAccountLoadFailed(true);
        setPageError(
          err instanceof Error
            ? err.message
            : "Could not load payment gateway accounts.",
        );
      } finally {
        if (current) setLoading(false);
      }
    }
    void load();
    return () => {
      current = false;
    };
  }, [apiConfigured, accountReloadKey]);

  useEffect(() => {
    if (!apiConfigured || !manage) return;
    let current = true;
    async function loadGateways() {
      try {
        const rows = await getPaymentGateways();
        if (!current) return;
        setPaymentGateways(rows);
        setGatewayCatalogState("loaded");
        setGatewayCatalogError("");
      } catch (err) {
        if (!current) return;
        setPaymentGateways([]);
        setGatewayCatalogState("failed");
        setGatewayCatalogError(
          err instanceof Error ? err.message : "Could not load payment gateways.",
        );
      }
    }
    void loadGateways();
    return () => {
      current = false;
    };
  }, [apiConfigured, manage, gatewayCatalogReloadKey]);

  useEffect(() => {
    if (
      !apiConfigured ||
      !selectedId
    ) {
      return;
    }
    const accountId = selectedId;
    const gatewayId = selectedGatewayId ?? "";
    const gatewayName = selectedGatewayName ?? "Unknown gateway";
    let current = true;
    async function loadChannels() {
      try {
        const enabled = await getAccountChannels(
          accountId,
          gatewayId,
          gatewayName,
        );
        if (!current) return;
        setRemoteChannels(enabled);
        setChannelLoadState({ accountId, status: "loaded" });
        const channelIds = enabled.map((channel) => channel.id);
        setAccounts((rows) =>
          rows.map((row) =>
            row.id === accountId ? { ...row, channels: channelIds } : row,
          ),
        );
      } catch (err) {
        if (current) {
          setChannelLoadState({ accountId, status: "failed" });
          setPageError(
            err instanceof Error
              ? err.message
              : "Could not load payment channels.",
          );
        }
      }
    }
    void loadChannels();
    return () => {
      current = false;
    };
  }, [
    apiConfigured,
    selectedId,
    selectedGatewayId,
    selectedGatewayName,
    channelReloadKey,
  ]);

  useEffect(() => {
    if (!apiConfigured || !selectedGatewayId || !selectedGatewayName) return;
    const gatewayId = selectedGatewayId;
    const gatewayName = selectedGatewayName;
    let current = true;
    async function loadGatewayChannels() {
      try {
        const rows = await getGatewayChannels(gatewayId, gatewayName);
        if (!current) return;
        setGatewayChannels(rows);
        setGatewayChannelLoadState({ gatewayId, status: "loaded" });
      } catch (err) {
        if (!current) return;
        setGatewayChannels([]);
        setGatewayChannelLoadState({ gatewayId, status: "failed" });
        setGatewayChannelError(
          err instanceof Error
            ? err.message
            : "Could not load available payment channels.",
        );
      }
    }
    void loadGatewayChannels();
    return () => {
      current = false;
    };
  }, [
    apiConfigured,
    selectedGatewayId,
    selectedGatewayName,
    gatewayChannelReloadKey,
  ]);

  function edit(account?: GatewayAccount) {
    if (!apiConfigured || !manage) return;
    setError("");
    setDraft(
      account
        ? { ...account, channels: [...account.channels], merchantSecret: "" }
        : {
            id: crypto.randomUUID(),
            gatewayId: "",
            gateway: "",
            organization: "",
            country: "ID",
            currency: "IDR",
            active: true,
            adminFee: 0,
            successUrl: "",
            failureUrl: "",
            pendingUrl: "",
            cancelUrl: "",
            channels: [],
            merchantSecret: "",
          },
    );
  }
  async function activateAccount(accountId: string) {
    if (!manage || !apiConfigured) return;
    const account = accounts.find((row) => row.id === accountId);
    if (!account) return;
    setPageError("");
    setAccountBusyId(accountId);
    try {
      const updated = await updatePaymentAccount(
        account,
        { active: true },
      );
      setAccounts((rows) =>
        rows.map((row) =>
          row.id === accountId
            ? { ...updated, channels: row.channels }
            : row,
        ),
      );
      setNotice(`${account.gateway} account activated.`);
    } catch (err) {
      setPageError(
        err instanceof Error ? err.message : "Could not activate account.",
      );
    } finally {
      setAccountBusyId("");
    }
  }
  async function setChannelEnabled(channel: PaymentChannel, enabled: boolean) {
    if (
      !manage ||
      !apiConfigured ||
      !selected?.active ||
      !hasLoadedChannels ||
      !hasLoadedGatewayChannels ||
      pendingChannelIds.length > 0
    ) {
      return;
    }
    const account = selected;
    setPageError("");
    setNotice("");
    setPendingChannelIds((ids) => [...ids, channel.id]);
    try {
      if (enabled) {
        await enablePaymentChannel(account.id, channel.id);
      } else {
        await disablePaymentChannel(account.id, channel.id);
      }

      const updateConnectedChannels = (rows: PaymentChannel[]) =>
        enabled
          ? rows.some((row) => row.id === channel.id)
            ? rows
            : [...rows, channel]
          : rows.filter((row) => row.id !== channel.id);
      const updateAccountChannels = (accountRows: GatewayAccount[]) =>
        accountRows.map((row) => {
          if (row.id !== account.id) return row;
          const channels = new Set(row.channels);
          if (enabled) channels.add(channel.id);
          else channels.delete(channel.id);
          return { ...row, channels: [...channels] };
        });

      setRemoteChannels(updateConnectedChannels);
      setAccounts(updateAccountChannels);
      setChannelLoadState({ accountId: account.id, status: "loaded" });
      setNotice(
        `${channel.name} ${enabled ? "enabled" : "removed"} ${enabled ? "for" : "from"} this account.`,
      );

      try {
        const connected = await getAccountChannels(
          account.id,
          account.gatewayId,
          account.gateway,
        );
        setRemoteChannels(connected);
        setChannelLoadState({ accountId: account.id, status: "loaded" });
        setAccounts((rows) =>
          rows.map((row) =>
            row.id === account.id
              ? { ...row, channels: connected.map((item) => item.id) }
              : row,
          ),
        );
      } catch (err) {
        setPageError(
          `Channel ${enabled ? "enabled" : "removed"}, but its status could not be refreshed: ${err instanceof Error ? err.message : "request failed"}`,
        );
      }
    } catch (err) {
      setPageError(
        err instanceof Error
          ? err.message
          : `Could not ${enabled ? "enable" : "remove"} payment channel.`,
      );
    } finally {
      setPendingChannelIds((ids) => ids.filter((id) => id !== channel.id));
    }
  }
  async function confirmDeactivate() {
    if (!manage || !apiConfigured || !deactivating) return;
    const account = deactivating;
    setPageError("");
    setAccountBusyId(account.id);
    try {
      const updated = await updatePaymentAccount(
        account,
        { active: false },
      );
      setAccounts((rows) =>
        rows.map((row) =>
          row.id === account.id
            ? { ...updated, channels: row.channels }
            : row,
        ),
      );
      setNotice("Gateway account deactivated.");
      setDeactivating(null);
    } catch (err) {
      setPageError(
        err instanceof Error ? err.message : "Could not deactivate account.",
      );
    } finally {
      setAccountBusyId("");
    }
  }
  return (
    <div className="space-y-5">
      {!apiConfigured && previewState === "populated" && (
        <PreviewNotice>
          Payment service is not configured. Sample payment accounts and
          channels are hidden on this page.
        </PreviewNotice>
      )}
      {previewAccountEmpty && (
        <PreviewNotice>
          Preview only: simulating an organization without a payment gateway
          account. No payment service request is sent.
        </PreviewNotice>
      )}
      {previewAccountFailure && (
        <PreviewNotice>
          Preview only: simulating a failed payment-account request. No payment
          service request is sent.
        </PreviewNotice>
      )}
      {pageError && !accountLoadFailed && (
        <p role="alert" className="text-sm text-destructive">
          {pageError}
        </p>
      )}
      {notice && (
        <p role="status" className="text-sm text-success">
          {notice}
        </p>
      )}
      {showAccountSetup ? (
        <Panel
          title="Payment gateway setup"
          description="Connect a gateway account before managing payment channels."
        >
          <div className="grid gap-6 p-5 lg:grid-cols-[minmax(0,1fr)_minmax(280px,0.8fr)] lg:p-6">
            <div className="space-y-4">
              <span className="flex size-12 items-center justify-center rounded-xl bg-primary/10 text-primary">
                <CreditCard className="size-6" aria-hidden="true" />
              </span>
              <div>
                <h2 className="text-lg font-semibold">
                  Connect your first payment gateway
                </h2>
                <p className="mt-2 max-w-2xl text-sm text-muted-foreground">
                  This organization does not have a payment gateway account yet.
                  Add an account to start connecting and managing its payment
                  channels.
                </p>
              </div>
              {manage && (
                <div className="space-y-2">
                  <Button
                    disabled={!apiConfigured || loading}
                    onClick={() => edit()}
                  >
                    <Plus className="size-4" aria-hidden="true" />
                    Add gateway account
                  </Button>
                  {!apiConfigured && (
                    <p className="text-xs text-muted-foreground">
                      Account setup becomes available when the payment service
                      is configured.
                    </p>
                  )}
                </div>
              )}
              {!manage && (
                <p className="text-sm text-muted-foreground">
                  A user with payment management access can connect a gateway
                  account.
                </p>
              )}
            </div>
            <ol className="grid gap-3 sm:grid-cols-3 lg:grid-cols-1">
              {[
                "Add the payment gateway account",
                "Configure the account credentials",
                "Connect the payment channels you need",
              ].map((step, index) => (
                <li
                  key={step}
                  className="flex items-start gap-3 rounded-lg border bg-card p-4"
                >
                  <span className="flex size-7 shrink-0 items-center justify-center rounded-full bg-muted text-sm font-semibold">
                    {index + 1}
                  </span>
                  <span className="pt-1 text-sm">{step}</span>
                </li>
              ))}
            </ol>
          </div>
        </Panel>
      ) : accountListFailed && !loading && accounts.length === 0 ? (
        <Panel
          title="Payment gateway accounts"
          description="The account list could not be confirmed."
        >
          <div className="space-y-3 p-5">
            <p role="alert" className="text-sm text-destructive">
              {accountLoadFailed
                ? pageError
                : "Simulated failure: payment gateway accounts could not be loaded."}
            </p>
            {accountLoadFailed && (
              <Button
                variant="outline"
                disabled={loading}
                onClick={() => setAccountReloadKey((key) => key + 1)}
              >
                Try again
              </Button>
            )}
          </div>
        </Panel>
      ) : (
      <div className="grid items-start gap-5 xl:grid-cols-[320px_1fr]">
        <Panel
          title="Pay-in Gateway Accounts"
          description="ID · TIAR"
        >
          <div className="space-y-3 p-5">
            {loading && (
              <p className="text-sm text-muted-foreground">
                Loading payment accounts…
              </p>
            )}
            {accounts.map((account) => (
              <div key={account.id} className="space-y-3">
                <button
                  type="button"
                  aria-pressed={selectedId === account.id}
                  className={`w-full rounded-xl border p-4 text-left transition-colors hover:border-primary/35 ${selectedId === account.id ? "border-primary bg-primary/5" : ""}`}
                  onClick={() => {
                    setPageError("");
                    setSelectedId(account.id);
                  }}
                >
                  <div className="flex items-center justify-between">
                    <span className="font-semibold">{account.gateway}</span>
                    <StatusBadge>
                      {account.active ? "Active" : "Inactive"}
                    </StatusBadge>
                  </div>
                  <p className="mt-3 text-xs text-muted-foreground">
                    {account.organization || "Organization"} · {account.currency} ·{" "}
                    {account.country === "ID" ? "Indonesia" : account.country}
                  </p>
                </button>
                {manage && (
                  <div className="mt-4 flex gap-2">
                    <Button
                      size="sm"
                      variant="outline"
                      disabled={accountBusyId === account.id}
                      onClick={() => edit(account)}
                    >
                      Edit
                    </Button>
                    {account.active ? (
                      <Button
                        size="sm"
                        variant="ghost"
                        disabled={accountBusyId === account.id}
                        onClick={() => setDeactivating(account)}
                      >
                        Deactivate
                      </Button>
                    ) : (
                      <Button
                        size="sm"
                        variant="outline"
                        disabled={accountBusyId === account.id}
                        onClick={() => activateAccount(account.id)}
                      >
                        Activate
                      </Button>
                    )}
                  </div>
                )}
              </div>
            ))}
            {manage && (
              <Button
                className="w-full"
                variant="outline"
                disabled={
                  !apiConfigured || loading
                }
                onClick={() => edit()}
              >
                <Plus className="size-4" />
                Add gateway account
              </Button>
            )}
            {!loading && accounts.length === 0 && (
              <p className="text-sm text-muted-foreground">
                {apiConfigured
                  ? "No payment gateway accounts found."
                  : "Configure the payment service to load payment accounts."}
              </p>
            )}
          </div>
        </Panel>
        <Panel
          title="Pay-in Configuration"
          description={
            selected
              ? `${selected.gateway} · ${selected.currency}`
              : "Select a gateway account"
          }
        >
          <div className="space-y-6 p-5">
            {selected && (
              <>
                <div className="border-b pb-6">
                  <h3 className="font-semibold">Pay-in Channels</h3>
                  <p className="mt-1 text-sm text-muted-foreground">
                    Turn on the channels this account should use for pay-in.
                  </p>
                </div>
                {!selected.active && (
                  <p className="rounded-lg bg-muted p-3 text-sm text-muted-foreground">
                    This account is inactive. Activate the account before
                    configuring channels.
                  </p>
                )}
                {(channelsLoading || gatewayChannelsLoading) && (
                  <p className="text-sm text-muted-foreground">
                    Loading payment channels…
                  </p>
                )}
                {channelLoadState?.accountId === selected.id &&
                  channelLoadState.status === "failed" && (
                    <div
                      className="flex flex-wrap items-center justify-between gap-3"
                      role="alert"
                    >
                      <p className="text-sm text-destructive">
                        Could not verify the current channel status for this
                        account.
                      </p>
                      <Button
                        type="button"
                        variant="outline"
                        onClick={() => {
                          setPageError("");
                          setChannelLoadState(null);
                          setChannelReloadKey((key) => key + 1);
                        }}
                      >
                        Try again
                      </Button>
                    </div>
                  )}
                {gatewayChannelLoadState?.gatewayId === selected.gatewayId &&
                  gatewayChannelLoadState.status === "failed" && (
                    <div
                      className="flex flex-wrap items-center justify-between gap-3"
                      role="alert"
                    >
                      <p className="text-sm text-destructive">
                        {gatewayChannelError}
                      </p>
                      <Button
                        type="button"
                        variant="outline"
                        onClick={() => {
                          setGatewayChannelLoadState({
                            gatewayId: selected.gatewayId,
                            status: "loading",
                          });
                          setGatewayChannelError("");
                          setGatewayChannelReloadKey((key) => key + 1);
                        }}
                      >
                        Try again
                      </Button>
                    </div>
                  )}
                {hasLoadedChannels &&
                  hasLoadedGatewayChannels &&
                  allChannels.length === 0 && (
                    <p className="text-sm text-muted-foreground">
                      No payment channels are available for this gateway.
                    </p>
                  )}
                {hasLoadedChannels &&
                  hasLoadedGatewayChannels &&
                  allChannels.length > 0 && (
                  <div className="space-y-6">
                    {channelTypes.map((type) => (
                      <section key={type} className="space-y-3">
                        <h3 className="text-sm font-semibold">
                          {paymentChannelTypeLabel(type)}
                        </h3>
                        <div className="grid gap-3 sm:grid-cols-2 lg:grid-cols-3">
                          {allChannels
                            .filter((channel) => channel.type === type)
                            .map((channel) => {
                              const enabled = connectedChannelIds.has(channel.id);
                              const pending = pendingChannelIds.includes(channel.id);
                              return (
                              <article
                                key={channel.id}
                                className={`flex min-w-0 flex-col items-center rounded-xl border p-4 text-center ${enabled ? "border-primary/40 bg-primary/5" : "bg-muted/15"}`}
                              >
                                {channel.logo ? (
                                  <Image
                                    src={`/images/payment-channels/${channel.logo}`}
                                    alt=""
                                    width={64}
                                    height={40}
                                    className="h-10 w-16 object-contain"
                                  />
                                ) : (
                                  <span className="flex size-10 items-center justify-center rounded-lg bg-primary/10 text-primary">
                                    <CreditCard
                                      className="size-5"
                                      aria-hidden="true"
                                    />
                                  </span>
                                )}
                                <h4 className="mt-3 text-sm font-semibold">
                                  {channel.name}
                                </h4>
                                {channel.description && (
                                  <p className="mt-1 text-xs text-muted-foreground">
                                    {channel.description}
                                  </p>
                                )}
                                <div className="mt-4 flex items-center gap-2">
                                  {manage ? (
                                    <>
                                      <Switch
                                        checked={enabled}
                                        disabled={
                                          !apiConfigured ||
                                          !selected.active ||
                                          channelsLoading ||
                                          gatewayChannelsLoading ||
                                          pendingChannelIds.length > 0
                                        }
                                        aria-label={`${enabled ? "Disable" : "Enable"} ${channel.name} for ${selected.gateway}`}
                                        onCheckedChange={(checked) =>
                                          void setChannelEnabled(channel, checked)
                                        }
                                      />
                                      <span className="text-xs text-muted-foreground">
                                        {pending
                                          ? enabled
                                            ? "Disabling…"
                                            : "Enabling…"
                                          : enabled
                                            ? "Enabled"
                                            : "Disabled"}
                                      </span>
                                    </>
                                  ) : (
                                    <span className="text-xs text-muted-foreground">
                                      {enabled ? "Enabled" : "Disabled"}
                                    </span>
                                  )}
                                </div>
                              </article>
                              );
                            })}
                        </div>
                      </section>
                    ))}
                  </div>
                )}
              </>
            )}
            {!selected && (
              <p className="text-sm text-muted-foreground">
                {apiConfigured
                  ? "Select a payment account to view its channels."
                  : "Configure the payment service to load payment channels."}
              </p>
            )}
          </div>
        </Panel>
      </div>
      )}
      <Dialog
        open={!!draft}
        onOpenChange={(open) => {
          if (!open) setDraft(null);
        }}
      >
        <DialogContent className="max-h-[90vh] overflow-y-auto">
          <DialogHeader>
            <DialogTitle>
              {accounts.some((a) => a.id === draft?.id) ? "Edit" : "Create"}{" "}
              gateway account
            </DialogTitle>
            <DialogDescription>
              Changes are sent to the configured payment service.
            </DialogDescription>
          </DialogHeader>
          {draft && (
            <form
              className="space-y-5"
              onSubmit={async (e) => {
                e.preventDefault();
                if (!manage || !apiConfigured) return;
                setError("");
                try {
                  const isExisting = accounts.some(
                    (account) => account.id === draft.id,
                  );
                  if (!isExisting && !draft.merchantSecret.trim()) {
                    throw new Error(
                      "Merchant secret is required to create an account.",
                    );
                  }
                  if (
                    !isExisting &&
                    !availableGateways.some(
                      (gateway) => gateway.id === draft.gatewayId,
                    )
                  ) {
                    throw new Error("Select an available payment gateway.");
                  }
                  validateGatewayAccount(draft);
                  setSaving(true);
                  const existing = accounts.find(
                    (account) => account.id === draft.id,
                  );
                  if (existing) {
                    const updated = await updatePaymentAccount(
                      existing,
                      toUpdateAccountPayload(draft),
                    );
                    setAccounts((rows) =>
                      rows.map((row) =>
                        row.id === updated.id
                          ? { ...updated, channels: row.channels }
                          : row,
                      ),
                    );
                    setNotice("Gateway account settings updated.");
                  } else {
                    const created = await createPaymentAccount(
                      toCreateAccountPayload(draft),
                      draft,
                    );
                    setAccounts((rows) => [...rows, created]);
                    setSelectedId(created.id);
                    setNotice("Gateway account created.");
                  }
                  setDraft(null);
                } catch (err) {
                  setError(
                    err instanceof Error
                      ? err.message
                      : "Could not save gateway settings.",
                  );
                } finally {
                  setSaving(false);
                }
              }}
            >
              <div className="grid gap-4 sm:grid-cols-2">
                {draftAccount ? (
                  <Field label="Gateway" value={draftAccount.gateway} disabled />
                ) : (
                  <SelectField
                    label="Gateway"
                    required
                    options={[
                      {
                        value: "",
                        label:
                          gatewayCatalogState === "loaded"
                            ? "Select a gateway"
                            : "Loading gateways…",
                      },
                      ...availableGateways.map((gateway) => ({
                        value: gateway.id,
                        label: gateway.name,
                      })),
                    ]}
                    disabled={
                      saving ||
                      gatewayCatalogState !== "loaded" ||
                      availableGateways.length === 0
                    }
                    value={draft.gatewayId}
                    onChange={(event) => {
                      const gateway = availableGateways.find(
                        (row) => row.id === event.target.value,
                      );
                      setDraft({
                        ...draft,
                        gatewayId: gateway?.id ?? "",
                        gateway: gateway?.name ?? "",
                      });
                    }}
                  />
                )}
                {!draftAccount && gatewayCatalogState === "failed" && (
                  <div
                    className="flex items-center justify-between gap-3 sm:col-span-2"
                    role="alert"
                  >
                    <p className="text-sm text-destructive">
                      {gatewayCatalogError}
                    </p>
                    <Button
                      type="button"
                      variant="outline"
                      onClick={() => {
                        setGatewayCatalogState("idle");
                        setGatewayCatalogError("");
                        setGatewayCatalogReloadKey((key) => key + 1);
                      }}
                    >
                      Try again
                    </Button>
                  </div>
                )}
                {!draftAccount &&
                  gatewayCatalogState === "loaded" &&
                  availableGateways.length === 0 && (
                    <p className="text-sm text-muted-foreground sm:col-span-2">
                      No active payment gateways are available.
                    </p>
                  )}
                <Field
                  label="Organization code"
                  value={draft.organization || "Assigned by payment service"}
                  disabled
                />
                <Field
                  label="Currency"
                  minLength={3}
                  maxLength={3}
                  required
                  disabled={accounts.some((account) => account.id === draft.id)}
                  value={draft.currency}
                  onChange={(e) =>
                    setDraft({
                      ...draft,
                      currency: e.target.value.toUpperCase(),
                    })
                  }
                />
                <SelectField
                  label="Status"
                  options={["Active", "Inactive"]}
                  disabled={!accounts.some((account) => account.id === draft.id)}
                  value={draft.active ? "Active" : "Inactive"}
                  onChange={(e) =>
                    setDraft({
                      ...draft,
                      active: e.target.value === "Active",
                    })
                  }
                />
              </div>
              <Field
                label="Merchant secret"
                type="password"
                autoComplete="new-password"
                disabled={saving}
                required={!accounts.some((account) => account.id === draft.id)}
                placeholder={
                  accounts.some((account) => account.id === draft.id)
                    ? "Leave blank to keep unchanged"
                    : "Enter merchant secret"
                }
                value={draft.merchantSecret}
                onChange={(e) =>
                  setDraft({ ...draft, merchantSecret: e.target.value })
                }
              />
              <p className="-mt-3 text-xs text-muted-foreground">
                Only sent when saving. It is not shown again or stored in this
                page.
              </p>
              <div className="grid gap-4 sm:grid-cols-2">
                {redirectFields.map((field) => (
                  <Field
                    key={field.key}
                    label={field.label}
                    type="url"
                    value={draft[field.key]}
                    onChange={(e) =>
                      setDraft({ ...draft, [field.key]: e.target.value })
                    }
                  />
                ))}
              </div>
              {error && (
                <p role="alert" className="text-sm text-destructive">
                  {error}
                </p>
              )}
              <DialogFooter>
                <Button
                  type="button"
                  variant="outline"
                  disabled={saving}
                  onClick={() => setDraft(null)}
                >
                  Cancel
                </Button>
                <Button disabled={saving}>
                  {saving ? "Saving…" : "Save settings"}
                </Button>
              </DialogFooter>
            </form>
          )}
        </DialogContent>
      </Dialog>
      <Dialog
        open={!!deactivating}
        onOpenChange={(open) => {
          if (!open) setDeactivating(null);
        }}
      >
        <DialogContent>
          <DialogHeader>
            <DialogTitle>Deactivate {deactivating?.gateway}?</DialogTitle>
            <DialogDescription>
              The payment account will become inactive. Its channel links will
              remain configured.
            </DialogDescription>
          </DialogHeader>
          <DialogFooter>
            <Button
              variant="outline"
              disabled={accountBusyId === deactivating?.id}
              onClick={() => setDeactivating(null)}
            >
              Cancel
            </Button>
            <Button
              disabled={accountBusyId === deactivating?.id}
              onClick={confirmDeactivate}
            >
              {accountBusyId === deactivating?.id
                ? "Deactivating…"
                : "Deactivate account"}
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>
    </div>
  );
}
