"use client";

import { useEffect, useMemo, useState } from "react";
import { UserCircle, Key, SignOut, ShareNetwork, Copy, CaretDown, Check, ArrowRight, Eye, EyeSlash, CreditCard, Minus, Plus } from "@phosphor-icons/react";
 import {
   Dialog,
   DialogContent,
   DialogDescription,
   DialogHeader,
   DialogTitle,
 } from "@/components/ui/dialog";
 import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Switch } from "@/components/ui/switch";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { DropdownMenu, DropdownMenuContent, DropdownMenuCheckboxItem, DropdownMenuTrigger } from "@/components/ui/dropdown-menu";
import { toast } from "sonner";
import { useTranslations } from "next-intl";
import {
  clearApiKeys,
  getDashscopeApiKey,
  getGeneratorModel,
  getMinimaxApiKey,
  getMinimaxGroupId,
  getSelectedModels,
  getSummaryModel,
  getTokendanceApiKey,
  getReviewModel,
  getZenmuxApiKey,
  getValidatedZenmuxKey,
  getValidatedDashscopeKey,
  getValidatedTokendanceKey,
  setGeneratorModel,
  setMinimaxApiKey,
  setMinimaxGroupId,
  setSelectedModels,
  setSummaryModel,
  setReviewModel,
  setTokendanceApiKey,
  setZenmuxApiKey,
  setDashscopeApiKey,
  setCustomKeyEnabled,
  setValidatedZenmuxKey,
  setValidatedDashscopeKey,
  setValidatedTokendanceKey,
  isCustomKeyEnabled as getCustomKeyEnabled,
} from "@/lib/api-keys";
import { getModelLogoPath } from "@/lib/model-logo";
import { supabase } from "@/lib/supabase";
import { REFERRAL_BONUS_ENABLED, SPRING_CAMPAIGN_ENABLED, REDEMPTION_CODE_ENABLED } from "@/lib/welfare-config";
import {
  ALL_MODELS,
  AVAILABLE_MODELS,
  DASHSCOPE_VALIDATION_MODEL,
  GENERATOR_MODEL,
  TOKENDANCE_VALIDATION_MODEL,
  ZENMUX_VALIDATION_MODEL,
  SUMMARY_MODEL,
  REVIEW_MODEL,
  filterPlayerModels,
  type ModelRef,
} from "@/types/game";
import type { SpringCampaignSnapshot } from "@/lib/spring-campaign";
 
 interface UserProfileModalProps {
   open: boolean;
   onOpenChange: (open: boolean) => void;
   email?: string | null;
   credits?: number | null;
   springCampaign?: SpringCampaignSnapshot | null;
   referralCode?: string | null;
   totalReferrals?: number | null;
   onChangePassword: () => void;
   onShareInvite: () => void;
  onSignOut: () => void | Promise<void>;
  onRedeemCode?: (code: string) => Promise<{
    success: boolean;
    credits?: number;
    creditsGranted?: number;
    error?: string;
  }>;
  onCustomKeyEnabledChange?: (value: boolean) => void;
  onCreditsChange?: () => void;
  defaultTab?: string;
 }
 
 export function UserProfileModal({
   open,
   onOpenChange,
   email,
   credits,
   springCampaign,
   referralCode,
   totalReferrals,
   onChangePassword,
   onShareInvite,
   onSignOut,
  onRedeemCode,
  onCustomKeyEnabledChange,
  onCreditsChange,
  defaultTab = "profile",
 }: UserProfileModalProps) {
  const t = useTranslations();
  const [zenmuxKey, setZenmuxKeyState] = useState("");
  const [dashscopeKey, setDashscopeKeyState] = useState("");
  const [tokendanceKey, setTokendanceKeyState] = useState("");
  const [minimaxKey, setMinimaxKeyState] = useState("");
  const [minimaxGroupId, setMinimaxGroupIdState] = useState("");
  const [showZenmuxKey, setShowZenmuxKey] = useState(false);
  const [showDashscopeKey, setShowDashscopeKey] = useState(false);
  const [showTokendanceKey, setShowTokendanceKey] = useState(false);
  const [showMinimaxKey, setShowMinimaxKey] = useState(false);
  const [showMinimaxGroupId, setShowMinimaxGroupId] = useState(false);
  const [isCustomKeyEnabled, setIsCustomKeyEnabled] = useState(false);
  const [selectedModels, setSelectedModelsState] = useState<string[]>([]);
  const [generatorModel, setGeneratorModelState] = useState("");
  const [summaryModel, setSummaryModelState] = useState("");
  const [reviewModel, setReviewModelState] = useState("");
  const [isModelSelectorOpen, setIsModelSelectorOpen] = useState(false);
  const [isValidatingZenmux, setIsValidatingZenmux] = useState(false);
  const [isValidatingDashscope, setIsValidatingDashscope] = useState(false);
  const [isValidatingTokendance, setIsValidatingTokendance] = useState(false);
  const [validatedKeys, setValidatedKeys] = useState<{ zenmux: string; dashscope: string; tokendance: string }>({
    zenmux: "",
    dashscope: "",
    tokendance: "",
  });
  const [purchaseQuantity, setPurchaseQuantity] = useState(10);
  const [purchaseQuantityInput, setPurchaseQuantityInput] = useState("10");
  const [isPurchasing, setIsPurchasing] = useState(false);
  const [isWechatQrOpen, setIsWechatQrOpen] = useState(false);
  const [redeemCodeInput, setRedeemCodeInput] = useState("");
  const [isRedeeming, setIsRedeeming] = useState(false);
  const profileActionGridClassName = REFERRAL_BONUS_ENABLED
    ? "grid grid-cols-2 gap-2"
    : "grid grid-cols-1 gap-2";
  const shouldShowSpringCampaignQuota = SPRING_CAMPAIGN_ENABLED && springCampaign?.active;
  const shouldShowSpringCampaignStatus = SPRING_CAMPAIGN_ENABLED;
  const getProviderLabel = (provider: ModelRef["provider"]) => {
    if (provider === "zenmux") return "Zenmux";
    if (provider === "tokendance") return "TokenDance";
    return t("customKey.dashscope.short");
  };

   const displayCredits = useMemo(() => {
    if (credits === null || credits === undefined) return t("userProfile.empty");
     return `${credits}`;
   }, [credits]);
 
  useEffect(() => {
    if (!open) return;
    let mounted = true;
    const nextZenmuxKey = getZenmuxApiKey();
    const nextDashscopeKey = getDashscopeApiKey();
    const nextTokendanceKey = getTokendanceApiKey();
    const nextMinimaxKey = getMinimaxApiKey();
    const nextMinimaxGroupId = getMinimaxGroupId();
    const nextSelectedModels = getSelectedModels();
    const nextGeneratorModel = getGeneratorModel();
    const nextSummaryModel = getSummaryModel();
    const nextReviewModel = getReviewModel();
    const storedCustomEnabled = getCustomKeyEnabled();
    if (mounted) {
      setZenmuxKeyState(nextZenmuxKey);
      setDashscopeKeyState(nextDashscopeKey);
      setTokendanceKeyState(nextTokendanceKey);
      setMinimaxKeyState(nextMinimaxKey);
      setMinimaxGroupIdState(nextMinimaxGroupId);
      setSelectedModelsState(nextSelectedModels);
      setGeneratorModelState(nextGeneratorModel);
      setSummaryModelState(nextSummaryModel);
      setReviewModelState(nextReviewModel);
      setIsCustomKeyEnabled(storedCustomEnabled);
      const z = nextZenmuxKey;
      const d = nextDashscopeKey;
      const td = nextTokendanceKey;
      setValidatedKeys({
        zenmux: z && getValidatedZenmuxKey() === z ? z : "",
        dashscope: d && getValidatedDashscopeKey() === d ? d : "",
        tokendance: td && getValidatedTokendanceKey() === td ? td : "",
      });
    }
    return () => {
      mounted = false;
    };
  }, [open]);

  const zenmuxConfigured = Boolean(zenmuxKey.trim());
  const dashscopeConfigured = Boolean(dashscopeKey.trim());
  const tokendanceConfigured = Boolean(tokendanceKey.trim());
  const modelPool = useMemo(() => {
    return ALL_MODELS;
  }, []);
  const defaultModelPool = useMemo(() => {
    return AVAILABLE_MODELS;
  }, []);
  const availableModelPool = useMemo(() => {
    const providers = new Set<ModelRef["provider"]>();
    if (zenmuxConfigured) providers.add("zenmux");
    if (dashscopeConfigured) providers.add("dashscope");
    if (tokendanceConfigured) providers.add("tokendance");
    if (providers.size === 0) return [];
    return modelPool.filter((ref) => providers.has(ref.provider));
  }, [dashscopeConfigured, modelPool, tokendanceConfigured, zenmuxConfigured]);
  const defaultAvailableModels = useMemo(() => {
    const providers = new Set<ModelRef["provider"]>();
    if (zenmuxConfigured) providers.add("zenmux");
    if (dashscopeConfigured) providers.add("dashscope");
    if (tokendanceConfigured) providers.add("tokendance");
    if (providers.size === 0) return [];
    return defaultModelPool.filter((ref) => providers.has(ref.provider));
  }, [dashscopeConfigured, defaultModelPool, tokendanceConfigured, zenmuxConfigured]);
  const playerModelPool = useMemo(() => {
    return filterPlayerModels(availableModelPool);
  }, [availableModelPool]);
  const defaultPlayerModels = useMemo(() => {
    return filterPlayerModels(defaultAvailableModels);
  }, [defaultAvailableModels]);

  useEffect(() => {
    if (!isCustomKeyEnabled) return;
    const availableSet = new Set(availableModelPool.map((ref) => ref.model));
    const playerSet = new Set(playerModelPool.map((ref) => ref.model));
    setSelectedModelsState((prev) => {
      const filtered = prev.filter((m) => playerSet.has(m));
      if (filtered.length > 0) return filtered;
      return defaultPlayerModels.map((ref) => ref.model).filter((m) => playerSet.has(m));
    });
    setGeneratorModelState((prev) => {
      if (prev && availableSet.has(prev)) return prev;
      if (availableSet.has(GENERATOR_MODEL)) return GENERATOR_MODEL;
      return availableModelPool[0]?.model ?? "";
    });
    setSummaryModelState((prev) => {
      if (prev && availableSet.has(prev)) return prev;
      if (availableSet.has(SUMMARY_MODEL)) return SUMMARY_MODEL;
      return availableModelPool[0]?.model ?? "";
    });
    setReviewModelState((prev) => {
      if (prev && availableSet.has(prev)) return prev;
      if (availableSet.has(REVIEW_MODEL)) return REVIEW_MODEL;
      return availableModelPool[0]?.model ?? "";
    });
  }, [availableModelPool, defaultPlayerModels, isCustomKeyEnabled, playerModelPool]);

  const selectedModelSummary = useMemo(() => {
    if (selectedModels.length === 0) return t("customKey.selectModel");
    const preview = selectedModels.slice(0, 2).join(t("customKey.modelJoiner"));
    if (selectedModels.length <= 2) return preview;
    return t("customKey.modelCount", { preview, count: selectedModels.length });
  }, [selectedModels]);

  // Close model selector when modal closes
  useEffect(() => {
    if (!open) setIsModelSelectorOpen(false);
  }, [open]);

   const handleCopyReferral = async () => {
    if (!REFERRAL_BONUS_ENABLED || !referralCode) return;
     try {
       await navigator.clipboard.writeText(referralCode);
      toast(t("userProfile.toasts.copySuccess"));
     } catch {
      toast(t("userProfile.toasts.copyFail.title"), {
        description: t("userProfile.toasts.copyFail.description"),
      });
     }
   };
 
  const handleSignOut = async () => {
    try {
      await onSignOut();
    } finally {
      onOpenChange(false);
    }
  };

  const handleSaveKeys = () => {
    if (isCustomKeyEnabled) {
      const zenmuxOk = !zenmuxKey.trim() || validatedKeys.zenmux === zenmuxKey.trim();
      const dashscopeOk = !dashscopeKey.trim() || validatedKeys.dashscope === dashscopeKey.trim();
      const tokendanceOk = !tokendanceKey.trim() || validatedKeys.tokendance === tokendanceKey.trim();
      if (!zenmuxOk || !dashscopeOk || !tokendanceOk) {
        toast(t("customKey.toasts.notValidated"), { description: t("customKey.toasts.notValidatedDesc") });
        return;
      }
    }
    const availableSet = new Set(availableModelPool.map((ref) => ref.model));
    const playerAvailableSet = new Set(playerModelPool.map((ref) => ref.model));
    if (isCustomKeyEnabled && availableSet.size === 0) {
      // Prevent saving an unusable custom-key state with no LLM keys.
      toast(t("customKey.toasts.needLlmKey"), { description: t("customKey.toasts.needLlmKeyDesc") });
      return;
    }
    const nextSelectedModels = selectedModels.filter((m) => playerAvailableSet.has(m));
    const fallbackGenerator = availableSet.has(GENERATOR_MODEL)
      ? GENERATOR_MODEL
      : availableModelPool[0]?.model ?? "";
    const fallbackSummary = availableSet.has(SUMMARY_MODEL)
      ? SUMMARY_MODEL
      : availableModelPool[0]?.model ?? "";
    const fallbackReview = availableSet.has(REVIEW_MODEL)
      ? REVIEW_MODEL
      : availableModelPool[0]?.model ?? "";
    const nextGeneratorModel = availableSet.has(generatorModel) ? generatorModel : fallbackGenerator;
    const nextSummaryModel = availableSet.has(summaryModel) ? summaryModel : fallbackSummary;
    const nextReviewModel = availableSet.has(reviewModel) ? reviewModel : fallbackReview;
    const removedSelected = selectedModels.filter((m) => !playerAvailableSet.has(m));
    const generatorAdjusted = Boolean(generatorModel) && !availableSet.has(generatorModel);
    const summaryAdjusted = Boolean(summaryModel) && !availableSet.has(summaryModel);
    const reviewAdjusted = Boolean(reviewModel) && !availableSet.has(reviewModel);

    if (
      isCustomKeyEnabled &&
      (availableSet.size === 0 || removedSelected.length > 0 || generatorAdjusted || summaryAdjusted || reviewAdjusted)
    ) {
      toast(t("customKey.toasts.modelsAdjusted"), {
        description: t("customKey.toasts.modelsAdjustedDesc"),
      });
    }
    setZenmuxApiKey(zenmuxKey);
    setDashscopeApiKey(dashscopeKey);
    setTokendanceApiKey(tokendanceKey);
    setMinimaxApiKey(minimaxKey);
    setMinimaxGroupId(minimaxGroupId);
    setSelectedModels(nextSelectedModels);
    setGeneratorModel(nextGeneratorModel);
    setSummaryModel(nextSummaryModel);
    setReviewModel(nextReviewModel);
    setSelectedModelsState(nextSelectedModels);
    setGeneratorModelState(nextGeneratorModel);
    setSummaryModelState(nextSummaryModel);
    setReviewModelState(nextReviewModel);
    toast(t("customKey.toasts.saved"), { description: t("customKey.toasts.savedDesc") });
    onOpenChange(false);
  };

  const validateProviderKey = async (options: {
    provider: "zenmux" | "dashscope" | "tokendance";
    key: string;
    model: string;
  }) => {
    const { provider, key } = options;
    const headers: Record<string, string> = {
      "Content-Type": "application/json",
    };
    if (provider === "zenmux") {
      headers["X-Zenmux-Api-Key"] = key;
    } else if (provider === "dashscope") {
      headers["X-Dashscope-Api-Key"] = key;
    } else if (provider === "tokendance") {
      headers["X-Tokendance-Api-Key"] = key;
    }

    const response = await fetch("/api/validate-key", {
      method: "POST",
      headers,
    });

    if (!response.ok) {
      let detail = "";
      try {
        const data = await response.json();
        detail = typeof data?.error === "string" ? data.error : JSON.stringify(data);
      } catch {
        detail = await response.text();
      }
      throw new Error(detail || t("customKey.toasts.validateFailed"));
    }

    const data = await response.json();
    if (!data.valid) {
      throw new Error(data.error || t("customKey.toasts.validateFailed"));
    }
  };

  const handleValidateZenmux = async () => {
    if (isValidatingZenmux || !zenmuxKey.trim()) return;
    setIsValidatingZenmux(true);
    try {
      await validateProviderKey({
        provider: "zenmux",
        key: zenmuxKey.trim(),
        model: ZENMUX_VALIDATION_MODEL,
      });
      setValidatedKeys((prev) => ({ ...prev, zenmux: zenmuxKey.trim() }));
      setValidatedZenmuxKey(zenmuxKey.trim());
    } catch (error) {
      setValidatedKeys((prev) => ({ ...prev, zenmux: "" }));
      if (zenmuxKey.trim() === getValidatedZenmuxKey()) setValidatedZenmuxKey("");
      toast(t("customKey.toasts.validateFailed"), {
        description: t("customKey.toasts.validateFailedDesc"),
      });
    } finally {
      setIsValidatingZenmux(false);
    }
  };

  const handleValidateDashscope = async () => {
    if (isValidatingDashscope || !dashscopeKey.trim()) return;
    setIsValidatingDashscope(true);
    try {
      await validateProviderKey({
        provider: "dashscope",
        key: dashscopeKey.trim(),
        model: DASHSCOPE_VALIDATION_MODEL,
      });
      setValidatedKeys((prev) => ({ ...prev, dashscope: dashscopeKey.trim() }));
      setValidatedDashscopeKey(dashscopeKey.trim());
    } catch (error) {
      setValidatedKeys((prev) => ({ ...prev, dashscope: "" }));
      if (dashscopeKey.trim() === getValidatedDashscopeKey()) setValidatedDashscopeKey("");
      toast(t("customKey.toasts.validateFailed"), {
        description: t("customKey.toasts.validateFailedDesc"),
      });
    } finally {
      setIsValidatingDashscope(false);
    }
  };

  const handleValidateTokendance = async () => {
    if (isValidatingTokendance || !tokendanceKey.trim()) return;
    setIsValidatingTokendance(true);
    try {
      await validateProviderKey({
        provider: "tokendance",
        key: tokendanceKey.trim(),
        model: TOKENDANCE_VALIDATION_MODEL,
      });
      setValidatedKeys((prev) => ({
        ...prev,
        tokendance: tokendanceKey.trim(),
      }));
      setValidatedTokendanceKey(tokendanceKey.trim());
    } catch {
      setValidatedKeys((prev) => ({ ...prev, tokendance: "" }));
      if (tokendanceKey.trim() === getValidatedTokendanceKey()) {
        setValidatedTokendanceKey("");
      }
      toast(t("customKey.toasts.validateFailed"), {
        description: t("customKey.toasts.validateFailedDesc"),
      });
    } finally {
      setIsValidatingTokendance(false);
    }
  };

  const handleClearKeys = () => {
    clearApiKeys();
    setZenmuxKeyState("");
    setDashscopeKeyState("");
    setTokendanceKeyState("");
    setMinimaxKeyState("");
    setMinimaxGroupIdState("");
    setSelectedModelsState([]);
    setGeneratorModelState(getGeneratorModel());
    setSummaryModelState(getSummaryModel());
    setReviewModelState(getReviewModel());
    setIsCustomKeyEnabled(false);
    setValidatedKeys({ zenmux: "", dashscope: "", tokendance: "" });
    onCustomKeyEnabledChange?.(false);
    toast(t("customKey.toasts.cleared"));
  };

  const handlePurchase = async () => {
    if (isPurchasing || purchaseQuantity < 10) return;
    setIsPurchasing(true);
    try {
      // Get fresh access token to avoid using expired token
      const { data: { session } } = await supabase.auth.getSession();
      const token = session?.access_token;
      if (!token) {
        toast(t("customKey.payAsYouGo.error"));
        return;
      }

      const response = await fetch("/api/stripe/payment-link", {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
          Authorization: `Bearer ${token}`,
        },
        body: JSON.stringify({ quantity: purchaseQuantity }),
      });
      const data = await response.json();
      if (data.url) {
        window.location.href = data.url;
      } else {
        toast(t("customKey.payAsYouGo.error"));
      }
    } catch {
      toast(t("customKey.payAsYouGo.error"));
    } finally {
      setIsPurchasing(false);
    }
  };

  const handleRedeem = async () => {
    if (isRedeeming || !redeemCodeInput.trim() || !onRedeemCode) return;
    setIsRedeeming(true);
    try {
      const result = await onRedeemCode(redeemCodeInput);
      if (result.success) {
        toast(t("customKey.payAsYouGo.redeemSuccess", { count: result.creditsGranted ?? 5 }));
        setRedeemCodeInput("");
      } else {
        const errorKey = result.error as "invalid_code" | "already_redeemed" | "disabled" | undefined;
        const errorMsg = errorKey && t.has(`customKey.payAsYouGo.redeemError.${errorKey}`)
          ? t(`customKey.payAsYouGo.redeemError.${errorKey}`)
          : t("customKey.payAsYouGo.redeemError.default");
        toast(errorMsg);
      }
    } catch {
      toast(t("customKey.payAsYouGo.redeemError.default"));
    } finally {
      setIsRedeeming(false);
    }
  };

  const totalPrice = (purchaseQuantity * 0.5).toFixed(2);

  return (
    <Dialog open={open} onOpenChange={onOpenChange}>
      <DialogContent
        className="max-w-xl max-h-[85vh] overflow-y-auto"
        onScroll={() => { if (isModelSelectorOpen) setIsModelSelectorOpen(false); }}
      >
        <DialogHeader>
          <DialogTitle className="flex items-center gap-2">
            <UserCircle size={20} />
            {t("userProfile.title")}
          </DialogTitle>
          <DialogDescription>{t("userProfile.description")}</DialogDescription>
        </DialogHeader>

        <Tabs defaultValue={defaultTab} key={defaultTab}>
          <TabsList>
            <TabsTrigger value="profile">{t("customKey.tabs.profile")}</TabsTrigger>
            <TabsTrigger value="payAsYouGo">{t("customKey.tabs.payAsYouGo")}</TabsTrigger>
            <TabsTrigger value="custom">{t("customKey.tabs.custom")}</TabsTrigger>
          </TabsList>

          <TabsContent value="profile">
                <div className="space-y-4">
                  <div className="rounded-lg border-2 border-[var(--border-color)] bg-[var(--bg-card)] p-3 space-y-2 text-sm">
                    <div className="flex items-center justify-between">
                      <span className="text-[var(--text-muted)]">{t("userProfile.fields.email")}</span>
                      <span className="text-[var(--text-primary)]">{email ?? t("userProfile.loggedIn")}</span>
                    </div>
                    <div className="flex items-center justify-between">
                      <span className="text-[var(--text-muted)]">{t("userProfile.fields.credits")}</span>
                      <span className="text-[var(--text-primary)]">{displayCredits}</span>
                    </div>
                    {shouldShowSpringCampaignQuota && (
                      <div className="flex items-center justify-between">
                        <span className="text-[var(--text-muted)]">{t("userProfile.fields.springQuota")}</span>
                        <span className="text-[var(--text-primary)]">
                          {t("userProfile.fields.springQuotaValue", {
                            count: springCampaign.remainingQuota,
                            total: springCampaign.totalQuota,
                          })}
                        </span>
                      </div>
                    )}
                    {REFERRAL_BONUS_ENABLED && (
                      <>
                        <div className="flex items-center justify-between">
                          <span className="text-[var(--text-muted)]">{t("userProfile.fields.referrals")}</span>
                          <span className="text-[var(--text-primary)]">{totalReferrals ?? 0}</span>
                        </div>
                        <div className="flex items-center justify-between gap-3">
                          <span className="text-[var(--text-muted)]">{t("userProfile.fields.referralCode")}</span>
                          <div className="flex items-center gap-2">
                            <span className="text-[var(--text-primary)]">{referralCode ?? "—"}</span>
                            {referralCode && (
                              <button
                                type="button"
                                onClick={handleCopyReferral}
                                className="p-1 rounded hover:bg-[var(--bg-hover)] text-[var(--text-muted)] hover:text-[var(--text-primary)] transition-colors"
                                title={t("userProfile.actions.copy")}
                              >
                                <Copy size={14} />
                              </button>
                            )}
                          </div>
                        </div>
                      </>
                    )}
                    {shouldShowSpringCampaignStatus && (
                      <p className="text-xs text-[var(--text-muted)] pt-0.5">
                        {springCampaign?.active
                          ? t("customKey.springCampaign.active")
                          : t("customKey.springCampaign.ended")}
                      </p>
                    )}
                  </div>

                  <div className={profileActionGridClassName}>
                    <Button type="button" variant="outline" onClick={onChangePassword} className="gap-2">
                      <Key size={16} />
                      {t("userProfile.actions.changePassword")}
                    </Button>
                    {REFERRAL_BONUS_ENABLED && (
                      <Button type="button" variant="outline" onClick={onShareInvite} className="gap-2">
                        <ShareNetwork size={16} />
                        {t("userProfile.actions.shareInvite")}
                      </Button>
                    )}
                  </div>

                  <Button type="button" variant="outline" onClick={handleSignOut} className="w-full gap-2">
                    <SignOut size={16} />
                    {t("userProfile.actions.signOut")}
                  </Button>
                </div>
              </TabsContent>

          <TabsContent value="payAsYouGo">
            <div className="space-y-4">
              {REDEMPTION_CODE_ENABLED && (
                <>
                  <section className="rounded-lg border border-[var(--border-color)] bg-[var(--bg-card)] p-4 space-y-4">
                    <div>
                      <h3 className="text-sm font-medium text-[var(--text-primary)]">{t("customKey.payAsYouGo.purchaseTitle")}</h3>
                      <p className="text-xs text-[var(--text-muted)] mt-1">{t("customKey.payAsYouGo.purchaseDesc")}</p>
                    </div>
                    <div className="flex justify-center">
                      <img
                        src="/pay.png"
                        alt="Purchase QR Code"
                        className="w-48 h-48 object-contain rounded-lg"
                      />
                    </div>
                    <a
                      href="https://pay.ldxp.cn/item/j9arl2"
                      target="_blank"
                      rel="noopener noreferrer"
                      className="flex items-center justify-center gap-2 w-full rounded-md border border-[var(--border-color)] bg-[var(--bg-secondary)] px-3 py-2 text-sm font-medium text-[var(--text-primary)] transition-colors hover:bg-[var(--bg-hover)]"
                    >
                      {t("customKey.payAsYouGo.openPurchaseLink")}
                      <ArrowRight size={14} />
                    </a>
                  </section>

                  <section className="rounded-lg border border-[var(--border-color)] bg-[var(--bg-card)] p-4 space-y-3">
                    <div>
                      <h3 className="text-sm font-medium text-[var(--text-primary)]">{t("customKey.payAsYouGo.redeemTitle")}</h3>
                      <p className="text-xs text-[var(--text-muted)] mt-1">{t("customKey.payAsYouGo.redeemHint")}</p>
                    </div>
                    <div className="flex gap-2">
                      <Input
                        value={redeemCodeInput}
                        onChange={(e) => setRedeemCodeInput(e.target.value)}
                        placeholder={t("customKey.payAsYouGo.redeemPlaceholder")}
                        className="flex-1"
                        disabled={isRedeeming}
                        onKeyDown={(e) => {
                          if (e.key === "Enter" && redeemCodeInput.trim() && !isRedeeming) {
                            void handleRedeem();
                          }
                        }}
                      />
                      <Button
                        type="button"
                        onClick={() => void handleRedeem()}
                        disabled={isRedeeming || !redeemCodeInput.trim()}
                        className="gap-2"
                      >
                        <CreditCard size={16} />
                        {isRedeeming ? t("customKey.payAsYouGo.redeeming") : t("customKey.payAsYouGo.redeemButton")}
                      </Button>
                    </div>
                  </section>
                </>
              )}

              <section className="rounded-lg border border-[var(--border-color)] bg-[var(--bg-card)] p-4 space-y-4">
                <div className="flex items-center justify-between">
                  <span className="text-sm text-[var(--text-muted)]">{t("customKey.payAsYouGo.pricePerGame", { price: "0.50" })}</span>
                </div>

                <div className="space-y-2">
                  <Label className="text-xs">{t("customKey.payAsYouGo.quantity")}</Label>
                  <div className="flex items-center gap-2">
                    <Button
                      type="button"
                      variant="outline"
                      size="sm"
                      onClick={() => {
                        const newVal = Math.max(10, purchaseQuantity - 1);
                        setPurchaseQuantity(newVal);
                        setPurchaseQuantityInput(newVal.toString());
                      }}
                      disabled={purchaseQuantity <= 10}
                      className="h-9 w-9 p-0"
                    >
                      <Minus size={16} />
                    </Button>
                    <Input
                      type="number"
                      min={10}
                      max={100}
                      value={purchaseQuantityInput}
                      onChange={(e) => {
                        const inputValue = e.target.value;
                        setPurchaseQuantityInput(inputValue);
                        // Allow empty input for better UX
                        if (inputValue === "") {
                          return;
                        }
                        const val = parseInt(inputValue, 10);
                        if (!isNaN(val) && val >= 10) {
                          setPurchaseQuantity(Math.min(100, Math.max(10, val)));
                        }
                      }}
                      onBlur={(e) => {
                        const inputValue = e.target.value;
                        if (inputValue === "" || isNaN(parseInt(inputValue, 10))) {
                          setPurchaseQuantityInput("10");
                          setPurchaseQuantity(10);
                        } else {
                          const val = parseInt(inputValue, 10);
                          const clampedVal = Math.min(100, Math.max(10, val));
                          setPurchaseQuantityInput(clampedVal.toString());
                          setPurchaseQuantity(clampedVal);
                        }
                      }}
                      className="h-9 w-20 text-center [appearance:textfield] [&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none"
                    />
                    <Button
                      type="button"
                      variant="outline"
                      size="sm"
                      onClick={() => {
                        const newVal = Math.min(100, purchaseQuantity + 1);
                        setPurchaseQuantity(newVal);
                        setPurchaseQuantityInput(newVal.toString());
                      }}
                      disabled={purchaseQuantity >= 100}
                      className="h-9 w-9 p-0"
                    >
                      <Plus size={16} />
                    </Button>
                  </div>
                  <div className="space-y-1">
                    <p className="text-xs text-[var(--text-muted)]">{t("customKey.payAsYouGo.minQuantity")}</p>
                    <p className="text-xs text-[var(--text-muted)] opacity-70">{t("customKey.payAsYouGo.minQuantityHint")}</p>
                  </div>
                </div>

                <div className="border-t border-[var(--border-color)] pt-4">
                  <div className="flex items-center justify-between mb-4">
                    <span className="text-sm font-medium text-[var(--text-primary)]">{t("customKey.payAsYouGo.total")}</span>
                    <span className="text-lg font-semibold text-[var(--color-gold)]">${totalPrice}</span>
                  </div>
                  <Button
                    type="button"
                    onClick={handlePurchase}
                    disabled={isPurchasing}
                    className="w-full gap-2"
                  >
                    <CreditCard size={16} />
                    {isPurchasing ? t("customKey.payAsYouGo.redirecting") : t("customKey.payAsYouGo.purchase")}
                  </Button>
                </div>
              </section>
            </div>
          </TabsContent>

          <TabsContent value="custom">
            <div className="space-y-5">
              {/* 1. Enable custom key */}
              <section className="rounded-lg border border-[var(--border-color)] bg-[var(--bg-card)] p-4">
                <div className="flex items-center justify-between gap-4">
                  <div>
                    <h3 className="text-sm font-medium text-[var(--text-primary)]">{t("customKey.title")}</h3>
                    <p className="text-xs text-[var(--text-muted)] mt-1">{t("customKey.description")}</p>
                  </div>
                  <Switch
                    checked={isCustomKeyEnabled}
                    onCheckedChange={(value) => {
                      setIsCustomKeyEnabled(value);
                      setCustomKeyEnabled(value);
                      onCustomKeyEnabledChange?.(value);
                    }}
                  />
                </div>
              </section>

              {isCustomKeyEnabled && (
                <>
                  {/* 2. LLM Keys — at least one required */}
                  <section className="rounded-lg border border-[var(--border-color)] bg-[var(--bg-card)] p-4 space-y-4">
                    <div>
                      <h3 className="text-sm font-medium text-[var(--text-primary)]">{t("customKey.llmKey.title")}</h3>
                      <p className="text-xs text-[var(--text-muted)] mt-1">{t("customKey.llmKey.description")}</p>
                    </div>

                    <div className="space-y-2">
                      <Label htmlFor="tokendance-key" className="text-xs">{t("customKey.tokendance.label")}</Label>

                      <div className="flex gap-2">
                        <Input
                          id="tokendance-key"
                          name="wolfcha-tokendance-api-key"
                          type={showTokendanceKey ? "text" : "password"}
                          autoComplete="new-password"
                          placeholder={t("customKey.tokendance.placeholder")}
                          value={tokendanceKey}
                          onChange={(e) => {
                            setTokendanceKeyState(e.target.value);
                            setValidatedKeys((prev) => ({ ...prev, tokendance: "" }));
                          }}
                          className="flex-1"
                        />
                        <Button
                          type="button"
                          variant="outline"
                          size="sm"
                          onClick={() => setShowTokendanceKey((v) => !v)}
                          aria-label={showTokendanceKey ? t("customKey.tokendance.hide") : t("customKey.tokendance.show")}
                        >
                          {showTokendanceKey ? <EyeSlash size={16} /> : <Eye size={16} />}
                        </Button>
                        <Button
                          type="button"
                          variant="outline"
                          size="sm"
                          onClick={handleValidateTokendance}
                          disabled={
                            isValidatingTokendance ||
                            !tokendanceKey.trim() ||
                            (!!validatedKeys.tokendance && validatedKeys.tokendance === tokendanceKey.trim())
                          }
                        >
                          {isValidatingTokendance ? t("customKey.validating") : validatedKeys.tokendance && validatedKeys.tokendance === tokendanceKey.trim() ? <Check size={16} className="text-[var(--color-success)]" /> : t("customKey.validate")}
                        </Button>
                      </div>

                      <a href="https://tokendance.agent-universe.cn/?ref=wolfcha" target="_blank" rel="noopener noreferrer" className="flex items-center gap-2 rounded-md border border-[var(--border-color)] bg-[var(--bg-secondary)] px-2.5 py-2 transition-colors hover:bg-[var(--bg-hover)]">
                        <img src="/sponsor/tokendance-icon.svg" alt="" className="h-6 w-6 shrink-0 rounded object-contain" />
                        <div className="min-w-0 flex-1">
                          <span className="text-xs font-medium text-[var(--text-primary)]">{t("customKey.tokendance.get")}</span>
                          <span className="text-[11px] text-[var(--text-muted)] ml-1.5">{t("customKey.tokendance.note")}</span>
                        </div>
                        <ArrowRight size={14} className="shrink-0 text-[var(--text-muted)]" />
                      </a>
                    </div>

                    <div className="border-t border-[var(--border-color)] pt-3 space-y-2">
                      <Label htmlFor="zenmux-key" className="text-xs">{t("customKey.zenmux.label")}</Label>
                     
                      <div className="flex gap-2">
                        <Input
                          id="zenmux-key"
                          name="wolfcha-zenmux-api-key"
                          type={showZenmuxKey ? "text" : "password"}
                          autoComplete="new-password"
                          placeholder={t("customKey.zenmux.placeholder")}
                          value={zenmuxKey}
                          onChange={(e) => {
                            setZenmuxKeyState(e.target.value);
                            setValidatedKeys((prev) => ({ ...prev, zenmux: "" }));
                          }}
                          className="flex-1"
                        />
                        <Button
                          type="button"
                          variant="outline"
                          size="sm"
                          onClick={() => setShowZenmuxKey((v) => !v)}
                          aria-label={showZenmuxKey ? t("customKey.zenmux.hide") : t("customKey.zenmux.show")}
                        >
                          {showZenmuxKey ? <EyeSlash size={16} /> : <Eye size={16} />}
                        </Button>
                        <Button type="button" variant="outline" size="sm" onClick={handleValidateZenmux} disabled={isValidatingZenmux || !zenmuxKey.trim() || (!!validatedKeys.zenmux && validatedKeys.zenmux === zenmuxKey.trim())}>
                          {isValidatingZenmux ? t("customKey.validating") : validatedKeys.zenmux && validatedKeys.zenmux === zenmuxKey.trim() ? <Check size={16} className="text-[var(--color-success)]" /> : t("customKey.validate")}
                        </Button>
                      </div>
                      <a href="https://zenmux.ai/invite/DMMBVZ" target="_blank" rel="noopener noreferrer" className="flex items-center gap-2 rounded-md border-2 border-[var(--color-accent)] bg-[var(--color-accent-bg)] px-2.5 py-2 transition-all hover:shadow-md">
                        <img src="/sponsor/zenmux.png" alt="" className="h-6 w-6 shrink-0 rounded object-contain" />
                        <div className="min-w-0 flex-1">
                          <span className="text-xs font-medium text-[var(--text-primary)]">{t("customKey.zenmux.get")}</span>
                          <span className="text-[11px] text-[var(--text-muted)] ml-1.5">{t("customKey.zenmux.note")}</span>
                        </div>
                        <ArrowRight size={14} className="shrink-0 text-[var(--color-accent)]" />
                      </a>
                    </div>

                    <div className="border-t border-[var(--border-color)] pt-3 space-y-2">
                      <Label htmlFor="dashscope-key" className="text-xs">{t("customKey.dashscope.label")}</Label>
                     
                      <div className="flex gap-2">
                        <Input
                          id="dashscope-key"
                          name="wolfcha-dashscope-api-key"
                          type={showDashscopeKey ? "text" : "password"}
                          autoComplete="new-password"
                          placeholder={t("customKey.dashscope.placeholder")}
                          value={dashscopeKey}
                          onChange={(e) => {
                            setDashscopeKeyState(e.target.value);
                            setValidatedKeys((prev) => ({ ...prev, dashscope: "" }));
                          }}
                          className="flex-1"
                        />
                        <Button
                          type="button"
                          variant="outline"
                          size="sm"
                          onClick={() => setShowDashscopeKey((v) => !v)}
                          aria-label={showDashscopeKey ? t("customKey.dashscope.hide") : t("customKey.dashscope.show")}
                        >
                          {showDashscopeKey ? <EyeSlash size={16} /> : <Eye size={16} />}
                        </Button>
                        <Button type="button" variant="outline" size="sm" onClick={handleValidateDashscope} disabled={isValidatingDashscope || !dashscopeKey.trim() || (!!validatedKeys.dashscope && validatedKeys.dashscope === dashscopeKey.trim())}>
                          {isValidatingDashscope ? t("customKey.validating") : validatedKeys.dashscope && validatedKeys.dashscope === dashscopeKey.trim() ? <Check size={16} className="text-[var(--color-success)]" /> : t("customKey.validate")}
                        </Button>
                      </div>

                      <a href="https://bailian.console.aliyun.com/" target="_blank" rel="noopener noreferrer" className="flex items-center gap-2 rounded-md border border-[var(--border-color)] bg-[var(--bg-secondary)] px-2.5 py-2 transition-colors hover:bg-[var(--bg-hover)]">
                        <img src="/sponsor/bailian.png" alt="" className="h-6 w-6 shrink-0 rounded object-contain" />
                        <div className="min-w-0 flex-1">
                          <span className="text-xs font-medium text-[var(--text-primary)]">{t("customKey.dashscope.get")}</span>
                          <span className="text-[11px] text-[var(--text-muted)] ml-1.5">{t("customKey.dashscope.note")}</span>
                        </div>
                        <ArrowRight size={14} className="shrink-0 text-[var(--text-muted)]" />
                      </a>
                    </div>

                  </section>

                  {/* 3. Model config — only when at least one LLM key is configured */}
                  {availableModelPool.length > 0 && (
                    <section className="rounded-lg border border-[var(--border-color)] bg-[var(--bg-card)] p-4 space-y-4">
                      <div>
                        <h3 className="text-sm font-medium text-[var(--text-primary)]">{t("customKey.modelConfig.title")}</h3>
                        <p className="text-xs text-[var(--text-muted)] mt-1">{t("customKey.modelConfig.description")}</p>
                      </div>

                      <div className="grid gap-3 sm:grid-cols-2">
                        <div className="space-y-1.5">
                          <Label htmlFor="generator-model" className="text-xs">{t("customKey.modelConfig.generator")}</Label>
                          <Select
                            value={availableModelPool.some((r) => r.model === generatorModel) ? generatorModel : ""}
                            onValueChange={(v) => setGeneratorModelState(v)}
                          >
                            <SelectTrigger id="generator-model"><SelectValue placeholder={t("customKey.selectModel")} /></SelectTrigger>
                            <SelectContent className="max-h-60">
                              {availableModelPool.map((r) => (
                                <SelectItem key={`${r.provider}:${r.model}`} value={r.model} label={r.model} description={getProviderLabel(r.provider)} icon={getModelLogoPath(r)} />
                              ))}
                            </SelectContent>
                          </Select>
                        </div>
                        <div className="space-y-1.5">
                          <Label htmlFor="summary-model" className="text-xs">{t("customKey.modelConfig.summary")}</Label>
                          <Select
                            value={availableModelPool.some((r) => r.model === summaryModel) ? summaryModel : ""}
                            onValueChange={(v) => setSummaryModelState(v)}
                          >
                            <SelectTrigger id="summary-model"><SelectValue placeholder={t("customKey.selectModel")} /></SelectTrigger>
                            <SelectContent className="max-h-60">
                              {availableModelPool.map((r) => (
                                <SelectItem key={`${r.provider}:${r.model}`} value={r.model} label={r.model} description={getProviderLabel(r.provider)} icon={getModelLogoPath(r)} />
                              ))}
                            </SelectContent>
                          </Select>
                        </div>
                        <div className="space-y-1.5 sm:col-span-2">
                          <Label htmlFor="review-model" className="text-xs">{t("customKey.modelConfig.review")}</Label>
                          <Select
                            value={availableModelPool.some((r) => r.model === reviewModel) ? reviewModel : ""}
                            onValueChange={(v) => setReviewModelState(v)}
                          >
                            <SelectTrigger id="review-model"><SelectValue placeholder={t("customKey.selectModel")} /></SelectTrigger>
                            <SelectContent className="max-h-60">
                              {availableModelPool.map((r) => (
                                <SelectItem key={`${r.provider}:${r.model}`} value={r.model} label={r.model} description={getProviderLabel(r.provider)} icon={getModelLogoPath(r)} />
                              ))}
                            </SelectContent>
                          </Select>
                        </div>
                      </div>

                      <div className="space-y-2">
                        <Label className="text-xs">{t("customKey.modelConfig.candidates")}</Label>
                        <p className="text-xs text-[var(--text-muted)]">{t("customKey.modelConfig.candidatesDesc")}</p>
                        <DropdownMenu open={isModelSelectorOpen} onOpenChange={setIsModelSelectorOpen}>
                          <DropdownMenuTrigger asChild>
                            <button
                              type="button"
                              className="flex h-9 w-full items-center justify-between gap-2 rounded-md border-2 border-[var(--border-color)] bg-[var(--bg-card)] px-3 py-2 text-sm text-[var(--text-primary)] transition-colors focus-visible:outline-none focus-visible:border-[var(--color-accent)]"
                            >
                              <span className="min-w-0 truncate text-left">{selectedModelSummary}</span>
                              <CaretDown size={16} className={`shrink-0 transition-transform ${isModelSelectorOpen ? "rotate-180" : ""}`} />
                            </button>
                          </DropdownMenuTrigger>
                        <DropdownMenuContent align="start" className="w-[var(--radix-dropdown-menu-trigger-width)]">
                            {playerModelPool.map((r) => (
                              <DropdownMenuCheckboxItem
                                key={`${r.provider}:${r.model}`}
                                checked={selectedModels.includes(r.model)}
                                onSelect={(e) => e.preventDefault()}
                                onCheckedChange={(checked) =>
                                  setSelectedModelsState((prev) =>
                                    checked ? [...prev, r.model] : prev.filter((m) => m !== r.model)
                                  )
                                }
                              >
                                <img src={getModelLogoPath(r)} alt="" className="h-4 w-4 shrink-0 rounded object-contain" />
                                <span className="min-w-0 flex-1 truncate text-[var(--text-primary)]">{r.model}</span>
                                <span className="shrink-0 text-xs text-[var(--text-muted)]">({getProviderLabel(r.provider)})</span>
                              </DropdownMenuCheckboxItem>
                            ))}
                          </DropdownMenuContent>
                        </DropdownMenu>
                      </div>
                    </section>
                  )}

                  {/* 4. Voice — optional Minimax */}
                  <section className="rounded-lg border border-[var(--border-color)] bg-[var(--bg-card)] p-4 space-y-3">
                    <div>
                      <h3 className="text-sm font-medium text-[var(--text-primary)]">{t("customKey.voice.title")}</h3>
                      <p className="text-xs text-[var(--text-muted)] mt-1">{t("customKey.voice.description")}</p>
                    </div>
                    <div className="grid gap-3 sm:grid-cols-2">
                      <div className="space-y-1.5">
                        <Label htmlFor="minimax-key" className="text-xs">{t("customKey.minimax.keyLabel")}</Label>
                        <div className="flex gap-2">
                          <Input
                            id="minimax-key"
                            name="wolfcha-minimax-api-key"
                            type={showMinimaxKey ? "text" : "password"}
                            autoComplete="new-password"
                            placeholder={t("customKey.optionalPlaceholder")}
                            value={minimaxKey}
                            onChange={(e) => setMinimaxKeyState(e.target.value)}
                            className="flex-1"
                          />
                          <Button
                            type="button"
                            variant="outline"
                            size="sm"
                            onClick={() => setShowMinimaxKey((v) => !v)}
                            aria-label={showMinimaxKey ? t("customKey.minimax.hide") : t("customKey.minimax.show")}
                          >
                            {showMinimaxKey ? <EyeSlash size={16} /> : <Eye size={16} />}
                          </Button>
                        </div>
                      </div>
                      <div className="space-y-1.5">
                        <Label htmlFor="minimax-group" className="text-xs">{t("customKey.minimax.groupLabel")}</Label>
                        <div className="flex gap-2">
                          <Input
                            id="minimax-group"
                            name="wolfcha-minimax-group-id"
                            type={showMinimaxGroupId ? "text" : "password"}
                            autoComplete="new-password"
                            placeholder={t("customKey.optionalPlaceholder")}
                            value={minimaxGroupId}
                            onChange={(e) => setMinimaxGroupIdState(e.target.value)}
                            className="flex-1"
                          />
                          <Button
                            type="button"
                            variant="outline"
                            size="sm"
                            onClick={() => setShowMinimaxGroupId((v) => !v)}
                            aria-label={showMinimaxGroupId ? t("customKey.minimax.hideGroup") : t("customKey.minimax.showGroup")}
                          >
                            {showMinimaxGroupId ? <EyeSlash size={16} /> : <Eye size={16} />}
                          </Button>
                        </div>
                      </div>
                    </div>
                  </section>

                  {/* 5. Actions */}
                  <div className="flex gap-2">
                    <Button type="button" variant="outline" onClick={handleClearKeys} className="flex-1">{t("customKey.actions.clear")}</Button>
                    <Button type="button" onClick={handleSaveKeys} className="flex-1">{t("customKey.actions.save")}</Button>
                  </div>
                </>
              )}
            </div>
          </TabsContent>
        </Tabs>
      </DialogContent>

    </Dialog>
  );
 }
