"use client"; import { useCallback, useEffect, useMemo, useState } from "react"; import Link from "next/link"; import { useRouter } from "next/navigation"; import type { User } from "@supabase/supabase-js"; import { ArrowLeft, Bot, CheckCircle2, Copy, KeyRound, Loader2, LogOut, RefreshCw, ShieldCheck, UserCircle2, } from "lucide-react"; import { useI18n } from "@/hooks/useI18n"; import { getSupabaseBrowserClient, hasSupabasePublicEnv, } from "@/lib/supabase/client"; import styles from "./AccountCenter.module.css"; type AuthMeResponse = { authenticated?: boolean; user_id?: string | null; email?: string | null; entitlement_mode?: string | null; subscription_required?: boolean; subscription_active?: boolean | null; }; function formatTime(value: string | undefined | null, locale: string) { if (!value) return ""; try { const dt = new Date(value); if (Number.isNaN(dt.getTime())) return ""; return new Intl.DateTimeFormat(locale, { year: "numeric", month: "2-digit", day: "2-digit", hour: "2-digit", minute: "2-digit", }).format(dt); } catch { return ""; } } function normalizeProvider(user: User | null) { const provider = String(user?.app_metadata?.provider || "").trim().toLowerCase(); if (provider) return provider; const providers = user?.app_metadata?.providers; if (Array.isArray(providers) && providers.length) { return String(providers[0] || "").trim().toLowerCase(); } return ""; } export function AccountCenter() { const { locale, t } = useI18n(); const router = useRouter(); const [loading, setLoading] = useState(true); const [refreshing, setRefreshing] = useState(false); const [errorText, setErrorText] = useState(""); const [copied, setCopied] = useState(false); const [updatedAt, setUpdatedAt] = useState(""); const [user, setUser] = useState(null); const [backend, setBackend] = useState(null); const supabaseReady = hasSupabasePublicEnv(); const loadSnapshot = useCallback(async () => { setErrorText(""); try { const userPromise = supabaseReady ? getSupabaseBrowserClient().auth.getUser() : Promise.resolve({ data: { user: null as User | null } }); const backendPromise = fetch("/api/auth/me", { cache: "no-store" }); const [userResult, backendResult] = await Promise.all([ userPromise, backendPromise, ]); setUser(userResult.data?.user ?? null); if (!backendResult.ok) { const raw = (await backendResult.text()).slice(0, 240); throw new Error(`HTTP ${backendResult.status} ${raw}`.trim()); } const backendJson = (await backendResult.json()) as AuthMeResponse; setBackend(backendJson); setUpdatedAt(new Date().toISOString()); } catch (error) { setErrorText(String(error)); } }, [supabaseReady]); useEffect(() => { let cancelled = false; const run = async () => { setLoading(true); await loadSnapshot(); if (!cancelled) setLoading(false); }; void run(); return () => { cancelled = true; }; }, [loadSnapshot]); const onRefresh = async () => { setRefreshing(true); await loadSnapshot(); setRefreshing(false); }; const onSignOut = async () => { if (supabaseReady) { try { const supabase = getSupabaseBrowserClient(); await supabase.auth.signOut(); } catch {} } router.replace("/auth/login"); }; const userId = backend?.user_id || user?.id || ""; const email = backend?.email || user?.email || ""; const providerRaw = normalizeProvider(user); const provider = providerRaw ? providerRaw.toUpperCase() : t("account.na"); const lastSignIn = formatTime(user?.last_sign_in_at, locale) || t("account.na"); const updatedAtLabel = formatTime(updatedAt, locale) || t("account.na"); const displayName = String(user?.user_metadata?.full_name || "").trim() || (email ? String(email).split("@")[0] : "") || t("account.guestName"); const initials = displayName.slice(0, 2).toUpperCase(); const modeLabel = useMemo(() => { const mode = String(backend?.entitlement_mode || "").trim().toLowerCase(); if (mode === "supabase") return t("account.mode.supabase"); if (mode === "legacy_token") return t("account.mode.legacy"); if (mode === "disabled") return t("account.mode.disabled"); return t("account.mode.unknown"); }, [backend?.entitlement_mode, t]); const subscriptionLabel = useMemo(() => { if (!backend?.subscription_required) return t("account.subscription.notRequired"); if (backend.subscription_active === true) return t("account.subscription.active"); if (backend.subscription_active === false) return t("account.subscription.inactive"); return t("account.subscription.unknown"); }, [backend?.subscription_active, backend?.subscription_required, t]); const bindCommand = userId ? `/bind ${userId}${email ? ` ${email}` : ""}` : "/bind "; const copyBindCommand = async () => { try { await navigator.clipboard.writeText(bindCommand); setCopied(true); window.setTimeout(() => setCopied(false), 1300); } catch {} }; return (

{t("account.title")}

{t("account.subtitle")}

{t("account.backDashboard")}
{initials || "PW"}

{displayName}

{email || t("account.na")}

{t("account.authenticated")} {backend?.subscription_active ? ( {t("account.subscriptionActive")} ) : backend?.subscription_required ? ( {t("account.subscriptionRequired")} ) : ( {t("account.subscriptionUnknown")} )}
{t("account.updatedAt", { time: updatedAtLabel })}
{loading ? (
{t("account.loading")}
) : null} {errorText ? (
{t("account.error", { message: errorText })}
) : null}

{t("account.card.membership")}

{t("account.field.mode")}
{modeLabel}
{t("account.field.backendStatus")}
{backend?.authenticated ? t("account.backend.ok") : t("account.backend.fail")}
{t("account.field.requirement")}
{backend?.subscription_required ? t("account.subscriptionRequired") : t("account.subscription.notRequired")}
{t("account.field.subscription")}
{subscriptionLabel}

{t("account.card.identity")}

{t("account.field.email")}
{email || t("account.na")}
{t("account.field.userId")}
{userId || t("account.na")}
{t("account.field.provider")}
{provider}
{t("account.field.lastSignIn")}
{lastSignIn}

{t("account.card.bot")}

{t("account.field.bindHint")}

{bindCommand}
{!supabaseReady ? (
NEXT_PUBLIC_SUPABASE_URL / ANON_KEY is not configured.
) : null}
); }