"use client";
import { useEffect, useState } from "react";
import Image from "next/image";
import { CreditCard } from "lucide-react";
import { Panel, PreviewNotice, StatusBadge } from "@/components/shared/page";
import { Field } from "@/components/shared/field";
import { Button } from "@/components/ui/button";
import { Switch } from "@/components/ui/switch";
import { useDashboardAuth } from "@/components/layout/dashboard-auth-context";
import { usePreviewRole } from "@/components/layout/preview-context";
import { canManage } from "@/lib/preview";
import {
  getAllPayoutChannels,
  getAccountPayoutChannelIds,
  getPaymentAccounts,
  enableAccountPayoutChannel,
  disableAccountPayoutChannel,
  updatePaymentAdminFee,
} from "@/features/payment-channel/api-client";
import {
  gatewayAccounts,
  withdrawalChannels,
} from "@/features/payment-channel/fixtures";
import {
  paymentChannelTypeLabel,
  validateGatewayAccount,
  type GatewayAccount,
  type PaymentChannel,
} from "@/features/payment-channel/model";
import { Editor } from "@/features/pricing/editor";

export function PayoutConfiguration() {
  const { apiConfigured } = useDashboardAuth();
  const manage = canManage(usePreviewRole());
  const [accounts, setAccounts] = useState<GatewayAccount[]>(
    apiConfigured ? [] : gatewayAccounts,
  );
  const [selectedId, setSelectedId] = useState(
    apiConfigured ? "" : gatewayAccounts[0].id,
  );
  const [payoutChannels, setPayoutChannels] = useState<PaymentChannel[]>([]);
  const [activePayoutChannelIdsByAccount, setActivePayoutChannelIdsByAccount] =
    useState<Record<string, string[]>>({});
  const [draft, setDraft] = useState<GatewayAccount | null>(null);
  const [notice, setNotice] = useState("");
  const [error, setError] = useState("");
  const [pageError, setPageError] = useState("");
  const [loading, setLoading] = useState(apiConfigured);
  const [catalogLoadState, setCatalogLoadState] = useState<
    "loading" | "loaded" | "failed"
  >(apiConfigured ? "loading" : "loaded");
  const [accountChannelLoadState, setAccountChannelLoadState] = useState<{
    accountId: string;
    status: "loaded" | "failed";
  } | null>(null);
  const [savingPayoutChannelIds, setSavingPayoutChannelIds] = useState<string[]>(
    [],
  );
  const [saving, setSaving] = useState(false);
  const selected = accounts.find((account) => account.id === selectedId);
  const channelsLoading = Boolean(
    apiConfigured &&
      selected &&
      (catalogLoadState === "loading" ||
        accountChannelLoadState?.accountId !== selected.id),
  );
  const hasLoadedChannels = Boolean(
    !apiConfigured ||
      (selected &&
        catalogLoadState === "loaded" &&
        accountChannelLoadState?.accountId === selected.id &&
        accountChannelLoadState.status === "loaded"),
  );
  const channelLoadFailed = Boolean(
    catalogLoadState === "failed" ||
      (selected &&
        accountChannelLoadState?.accountId === selected.id &&
        accountChannelLoadState.status === "failed"),
  );

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

  useEffect(() => {
    if (!apiConfigured) return;
    let current = true;
    async function loadChannels() {
      try {
        const allChannels = await getAllPayoutChannels();
        if (!current) return;
        setPayoutChannels(allChannels);
        setCatalogLoadState("loaded");
      } catch (err) {
        if (current) {
          setCatalogLoadState("failed");
          setPageError(
            err instanceof Error
              ? err.message
              : "Could not load payout channels.",
          );
        }
      }
    }
    void loadChannels();
    return () => {
      current = false;
    };
  }, [apiConfigured]);

  useEffect(() => {
    if (!apiConfigured || !selectedId) return;
    let current = true;
    async function loadAccountChannels() {
      try {
        const channelIds = await getAccountPayoutChannelIds(selectedId);
        if (!current) return;
        setActivePayoutChannelIdsByAccount((currentByAccount) => ({
          ...currentByAccount,
          [selectedId]: channelIds,
        }));
        setAccountChannelLoadState({ accountId: selectedId, status: "loaded" });
      } catch (err) {
        if (!current) return;
        setAccountChannelLoadState({ accountId: selectedId, status: "failed" });
        setPageError(
          err instanceof Error
            ? err.message
            : "Could not load payout channels for this account.",
        );
      }
    }
    void loadAccountChannels();
    return () => {
      current = false;
    };
  }, [apiConfigured, selectedId]);

  const localWithdrawalChannels = selected
    ? withdrawalChannels[selected.gateway] ?? []
    : [];
  const selectedGatewayChannels = selected
    ? payoutChannels
        .filter(
          (channel) =>
            !channel.gatewayId ||
            !selected.gatewayId ||
            channel.gatewayId === selected.gatewayId,
        )
    : [];
  const channels = apiConfigured
    ? hasLoadedChannels
      ? selectedGatewayChannels
      : []
    : localWithdrawalChannels;
  const channelTypes = [...new Set(channels.map((channel) => channel.type))].sort(
    (a, b) => paymentChannelTypeLabel(a).localeCompare(paymentChannelTypeLabel(b)),
  );
  const activePayoutChannelIds = selected
    ? new Set(activePayoutChannelIdsByAccount[selected.id] ?? [])
    : new Set<string>();

  async function setChannelEnabled(channel: PaymentChannel, enabled: boolean) {
    if (!manage || !selected?.active) return;
    setPageError("");
    setNotice("");
    if (apiConfigured) {
      const accountId = selected.id;
      setSavingPayoutChannelIds((current) =>
        current.includes(channel.id) ? current : [...current, channel.id],
      );
      try {
        if (enabled) {
          await enableAccountPayoutChannel(accountId, channel.id);
        } else {
          await disableAccountPayoutChannel(accountId, channel.id);
        }
        setActivePayoutChannelIdsByAccount((currentByAccount) => {
          const current = currentByAccount[accountId] ?? [];
          const next = enabled
            ? current.includes(channel.id)
              ? current
              : [...current, channel.id]
            : current.filter((id) => id !== channel.id);
          return { ...currentByAccount, [accountId]: next };
        });
        setNotice(
          `${channel.name} ${enabled ? "enabled" : "disabled"} for this account.`,
        );
      } catch (err) {
        setPageError(
          err instanceof Error
            ? err.message
            : `Could not ${enabled ? "enable" : "disable"} ${channel.name}.`,
        );
      } finally {
        setSavingPayoutChannelIds((current) =>
          current.filter((id) => id !== channel.id),
        );
      }
      return;
    }
    setAccounts((rows) =>
      rows.map((account) =>
        account.id === selected.id
          ? {
              ...account,
              channels: enabled
                ? account.channels.includes(channel.id)
                  ? account.channels
                  : [...account.channels, channel.id]
                : account.channels.filter((id) => id !== channel.id),
            }
          : account,
      ),
    );
    setNotice(
      `${channel.name} ${enabled ? "enabled" : "disabled"} in this preview.`,
    );
  }

  return (
    <div className="space-y-5">
      <PreviewNotice>
        {apiConfigured
          ? "Payout channels come from Monet's master catalog. Each account's enabled channels are loaded and updated separately."
          : "Payout configuration preview. Accounts and channel options use shared payment fixtures; edits stay local."}
      </PreviewNotice>
      {pageError && (
        <p role="alert" className="text-sm text-destructive">
          {pageError}
        </p>
      )}
      {notice && (
        <p role="status" className="text-sm text-success">
          {notice}
        </p>
      )}
      <div className="grid items-start gap-5 xl:grid-cols-[320px_1fr]">
        <Panel title="Payout 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) => (
              <button
                key={account.id}
                type="button"
                aria-pressed={selected?.id === account.id}
                className={`w-full rounded-xl border p-4 text-left ${selected?.id === 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>
                <p className="mt-1 text-xs text-muted-foreground">
                  Current admin fee: {account.currency}{" "}
                  {account.adminFee.toLocaleString()}
                </p>
              </button>
            ))}
            {!loading && accounts.length === 0 && (
              <p className="text-sm text-muted-foreground">
                No payment gateway accounts found.
              </p>
            )}
          </div>
        </Panel>
        <Panel
          title="Payout Configuration"
          description={
            selected
              ? `${selected.gateway} · ${selected.currency}`
              : "Select a gateway account"
          }
        >
          <div className="space-y-6 p-5">
            {selected ? (
              <>
                <div className="flex flex-wrap items-center justify-between gap-4 border-b pb-6">
                  <div>
                    <h3 className="font-semibold">Admin Fee Configuration</h3>
                    <p className="mt-1 text-sm text-muted-foreground">
                      Fee applied to a payout from this gateway.
                    </p>
                    <p className="mt-4 text-2xl font-semibold">
                      {selected.currency} {selected.adminFee.toLocaleString()}
                    </p>
                  </div>
                  {manage && (
                    <Button
                      variant="outline"
                      onClick={() => {
                        setDraft({ ...selected });
                        setError("");
                      }}
                    >
                      Edit Fee
                    </Button>
                  )}
                </div>
                <section>
                  <h3 className="font-semibold">Payout Channels</h3>
                  <p className="mt-1 text-sm text-muted-foreground">
                    All payout channels are listed; enabled status is specific to this account.
                  </p>
                  {!selected.active && (
                    <p className="mt-3 rounded-lg bg-muted p-3 text-sm text-muted-foreground">
                      {apiConfigured
                        ? "This account is inactive."
                        : "This account is inactive. Activate it before changing channel settings."}
                    </p>
                  )}
                  {channelsLoading && (
                    <p className="mt-3 text-sm text-muted-foreground">
                      Loading payout channels…
                    </p>
                  )}
                  <div className="mt-4 space-y-6">
                    {channelTypes.map((type) => (
                      <section key={type} className="space-y-3">
                        <h4 className="text-sm font-semibold">
                          {paymentChannelTypeLabel(type)}
                        </h4>
                        <div className="grid gap-3 sm:grid-cols-2 lg:grid-cols-3">
                          {channels
                            .filter((channel) => channel.type === type)
                            .map((channel) => {
                              const enabled = apiConfigured
                                ? activePayoutChannelIds.has(channel.id)
                                : selected.channels.includes(channel.id);
                              return (
                                <div
                                  key={channel.id}
                                  className={`flex 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={channel.name}
                                      width={64}
                                      height={40}
                                      className="h-10 w-16 object-contain"
                                    />
                                  ) : (
                                    <CreditCard className="size-10 text-primary" />
                                  )}
                                  <h5 className="mt-3 font-medium">
                                    {channel.name}
                                  </h5>
                                  <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={
                                          !selected.active ||
                                          channelsLoading ||
                                          savingPayoutChannelIds.includes(
                                            channel.id,
                                          )
                                        }
                                        aria-label={`${enabled ? "Disable" : "Enable"} ${channel.name}`}
                                        onCheckedChange={(checked) =>
                                          void setChannelEnabled(channel, checked)
                                        }
                                      />
                                    )}
                                    <span className="text-xs text-muted-foreground">
                                      {enabled ? "Enabled" : "Disabled"}
                                    </span>
                                  </div>
                                </div>
                              );
                            })}
                        </div>
                      </section>
                    ))}
                  </div>
                  {!channelsLoading &&
                    channels.length === 0 &&
                    !channelLoadFailed && (
                      <p className="mt-3 text-sm text-muted-foreground">
                        No payout channels are available for this gateway.
                      </p>
                    )}
                </section>
              </>
            ) : (
              <p className="text-sm text-muted-foreground">
                {loading
                  ? "Loading withdrawal settings…"
                  : "No payment account is available."}
              </p>
            )}
          </div>
        </Panel>
      </div>
      {draft && selected && (
        <Editor
          title="Edit Payout Admin Fee"
          open
          error={error}
          description={
            apiConfigured
              ? "The fee is saved to the payment service for this account."
              : "Changes are local to this preview and reset when you reload."
          }
          submitLabel={apiConfigured ? "Save fee" : "Save preview"}
          submitting={saving}
          onClose={() => setDraft(null)}
          onSubmit={async () => {
            if (!manage) return;
            setError("");
            setPageError("");
            setSaving(true);
            try {
              validateGatewayAccount(draft);
              if (apiConfigured) {
                await updatePaymentAdminFee(selected.id, draft.adminFee);
              }
              setAccounts((rows) =>
                rows.map((account) =>
                  account.id === draft.id
                    ? { ...account, adminFee: draft.adminFee }
                    : account,
                ),
              );
              setDraft(null);
              setNotice(
                apiConfigured
                  ? "Payout admin fee updated."
                  : "Payout admin fee saved locally.",
              );
            } catch (err) {
              setError(
                err instanceof Error
                  ? err.message
                  : "Could not update withdrawal admin fee.",
              );
            } finally {
              setSaving(false);
            }
          }}
        >
          <Field
            label={`Admin fee (${draft.currency})`}
            type="number"
            required
            min="0"
            step="0.01"
            value={Number.isFinite(draft.adminFee) ? draft.adminFee : ""}
            onChange={(e) =>
              setDraft({ ...draft, adminFee: e.target.valueAsNumber })
            }
          />
        </Editor>
      )}
    </div>
  );
}
