import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import type { AxiosError } from "axios";
import {
  ArrowLeft,
  ExternalLink,
  Info,
  Plus,
  Save,
  Shield,
  Sparkles,
  Trash2,
  Upload,
} from "lucide-react";
import { useEffect, useState } from "react";
import { Link, useNavigate, useParams } from "react-router-dom";
import { Badge } from "../../components/ui/badge";
import { Button } from "../../components/ui/button";
import {
  Card,
  CardContent,
  CardDescription,
  CardHeader,
  CardTitle,
} from "../../components/ui/card";
import { Input } from "../../components/ui/input";
import { Label } from "../../components/ui/label";
import { Switch } from "../../components/ui/switch";
import { Textarea } from "../../components/ui/textarea";
import { toast } from "../../components/ui/use-toast";
import type {
  ClientStatus,
  ClientType,
  ClientUpsertRequest,
} from "../../lib/devApi";
import {
  createClient,
  deleteClient,
  fetchClient,
  refreshHeadlessJwksCache,
  revokeHeadlessJwksCache,
  updateClient,
  updateClientStatus,
} from "../../lib/devApi";
import { t } from "../../lib/i18n";
import { cn } from "../../lib/utils";

interface ScopeItem {
  id: string;
  name: string;
  description: string;
  mandatory: boolean;
}

type SecurityProfile = "private" | "pkce";
type TokenEndpointAuthMethod =
  | "none"
  | "client_secret_basic"
  | "private_key_jwt";

const HEADLESS_LOGIN_ALLOWED_ALGORITHMS = [
  "RS256",
  "RS384",
  "RS512",
  "PS256",
  "PS384",
  "PS512",
  "ES256",
  "ES384",
  "ES512",
  "EdDSA",
] as const;

const HEADLESS_LOGIN_ALLOWED_ALGORITHM_SET = new Set<string>(
  HEADLESS_LOGIN_ALLOWED_ALGORITHMS,
);

function formatHeadlessParsedKeyLabel(
  kid: string | undefined,
  index: number,
): string {
  const trimmedKid = kid?.trim();
  if (trimmedKid) {
    return trimmedKid;
  }
  return `key #${index + 1}`;
}

function isTokenEndpointAuthMethod(
  value: string,
): value is TokenEndpointAuthMethod {
  return (
    value === "none" ||
    value === "client_secret_basic" ||
    value === "private_key_jwt"
  );
}

function readMetadataString(
  metadata: Record<string, unknown>,
  key: string,
): string {
  const value = metadata[key];
  return typeof value === "string" ? value : "";
}

function isValidUrl(value: string): boolean {
  try {
    const url = new URL(value);
    return url.protocol === "https:" || url.protocol === "http:";
  } catch {
    return false;
  }
}

function formatDateTime(value?: string) {
  if (!value) return "-";
  const date = new Date(value);
  if (Number.isNaN(date.getTime())) return value;
  return date.toLocaleString();
}

function ClientGeneralPage() {
  const params = useParams();
  const navigate = useNavigate();
  const queryClient = useQueryClient();
  const clientId = params.id;
  const isCreate = !clientId;
  const { data, isLoading, error } = useQuery({
    queryKey: ["client", clientId],
    queryFn: () => fetchClient(clientId as string),
    enabled: !isCreate,
  });

  const [name, setName] = useState("");
  const [description, setDescription] = useState("");
  const [logoUrl, setLogoUrl] = useState("");
  const [logoPreviewStatus, setLogoPreviewStatus] = useState<
    "idle" | "loading" | "loaded" | "error"
  >("idle");
  const [clientType, setClientType] = useState<ClientType>("private");
  const [status, setStatus] = useState<ClientStatus>("active");
  const [initialStatus, setInitialStatus] = useState<ClientStatus>("active");
  const [redirectUris, setRedirectUris] = useState("");

  // Public Key Registration States
  const [tokenEndpointAuthMethod, setTokenEndpointAuthMethod] =
    useState<TokenEndpointAuthMethod>("client_secret_basic");
  const [jwksUri, setJwksUri] = useState("");
  const [headlessLoginEnabled, setHeadlessLoginEnabled] = useState(false);

  const [scopes, setScopes] = useState<ScopeItem[]>(() => [
    {
      id: "1",
      name: "openid",
      description: t("msg.dev.clients.scopes.openid", "OIDC 인증 필수 스코프"),
      mandatory: true,
    },
    {
      id: "2",
      name: "profile",
      description: t("msg.dev.clients.scopes.profile", "기본 프로필 정보 접근"),
      mandatory: false,
    },
    {
      id: "3",
      name: "email",
      description: t("msg.dev.clients.scopes.email", "이메일 주소 접근"),
      mandatory: false,
    },
  ]);

  useEffect(() => {
    if (!data) return;
    const { client } = data;
    setName(client.name || client.id);
    setClientType(client.type);
    setStatus(client.status);
    setInitialStatus(client.status);

    const metadata = client.metadata ?? {};
    if (typeof metadata.description === "string")
      setDescription(metadata.description);
    if (typeof metadata.logo_url === "string") setLogoUrl(metadata.logo_url);

    const headlessEnabled = !!metadata.headless_login_enabled;
    setHeadlessLoginEnabled(headlessEnabled);

    const savedAuthMethod =
      client.tokenEndpointAuthMethod ||
      (client.type === "pkce" ? "none" : "client_secret_basic");
    const headlessAuthMethod = readMetadataString(
      metadata,
      "headless_token_endpoint_auth_method",
    );
    const selectedAuthMethod =
      headlessEnabled && isTokenEndpointAuthMethod(headlessAuthMethod)
        ? headlessAuthMethod
        : savedAuthMethod;
    if (isTokenEndpointAuthMethod(selectedAuthMethod)) {
      setTokenEndpointAuthMethod(selectedAuthMethod);
    }

    const headlessJwksUri = readMetadataString(metadata, "headless_jwks_uri");
    if (headlessJwksUri) {
      setJwksUri(headlessJwksUri);
    } else if (client.jwksUri) {
      setJwksUri(client.jwksUri);
    } else {
      setJwksUri("");
    }

    // Fallbacks from metadata if top-level fields are empty
    if (!client.tokenEndpointAuthMethod && !headlessEnabled) {
      const metaAuth = readMetadataString(
        metadata,
        "token_endpoint_auth_method",
      );
      if (isTokenEndpointAuthMethod(metaAuth)) {
        setTokenEndpointAuthMethod(metaAuth);
      }
    }

    if (!client.jwksUri && !headlessEnabled) {
      const metaJwksUri = readMetadataString(metadata, "jwks_uri");
      if (metaJwksUri) {
        setJwksUri(metaJwksUri);
      }
    }

    const savedScopes = metadata.structured_scopes as ScopeItem[] | undefined;
    if (savedScopes && Array.isArray(savedScopes)) {
      setScopes(savedScopes);
    } else {
      setScopes(
        client.scopes.map((s, idx) => ({
          id: String(idx + 1),
          name: s,
          description: "",
          mandatory: s === "openid",
        })),
      );
    }
  }, [data]);

  const securityProfile: SecurityProfile =
    clientType === "pkce" ? "pkce" : "private";
  const trimmedLogoUrl = logoUrl.trim();
  const hasLogoUrl = trimmedLogoUrl.length > 0;
  const hasValidLogoUrl = !hasLogoUrl || isValidUrl(trimmedLogoUrl);

  useEffect(() => {
    if (!hasLogoUrl) {
      setLogoPreviewStatus("idle");
      return;
    }
    if (!hasValidLogoUrl) {
      setLogoPreviewStatus("error");
      return;
    }
    setLogoPreviewStatus("loading");
  }, [hasLogoUrl, hasValidLogoUrl]);

  const handleSecurityProfileChange = (profile: SecurityProfile) => {
    setClientType(profile);
    if (profile === "pkce") {
      setTokenEndpointAuthMethod(
        headlessLoginEnabled ? "private_key_jwt" : "none",
      );
    } else {
      setTokenEndpointAuthMethod("client_secret_basic");
    }
  };

  const handleHeadlessToggle = (enabled: boolean) => {
    setHeadlessLoginEnabled(enabled);
    if (clientType === "pkce") {
      setTokenEndpointAuthMethod(enabled ? "private_key_jwt" : "none");
    }
  };

  const addScope = () => {
    const newId = String(Date.now());
    setScopes([
      ...scopes,
      { id: newId, name: "", description: "", mandatory: false },
    ]);
  };

  const updateScope = <K extends keyof ScopeItem>(
    id: string,
    field: K,
    value: ScopeItem[K],
  ) => {
    setScopes(
      scopes.map((scope) =>
        scope.id === id ? { ...scope, [field]: value } : scope,
      ),
    );
  };

  const removeScope = (id: string) => {
    setScopes(scopes.filter((s) => s.id !== id));
  };

  const handleStatusChange = (nextStatus: ClientStatus) => {
    setStatus(nextStatus);
    const statusLabel =
      nextStatus === "active"
        ? t("ui.common.status.active", "Active")
        : t("ui.common.status.inactive", "Inactive");
    toast(
      t(
        "msg.dev.clients.general.status_changed",
        "상태가 {{status}}로 변경되었습니다.",
        { status: statusLabel },
      ),
    );
  };

  const validationErrors: string[] = [];
  const trimmedJwksUri = jwksUri.trim();
  const currentHeadlessJwksCache = data?.headlessJwksCache;
  const parsedKeysForCurrentJwksUri =
    headlessLoginEnabled &&
    trimmedJwksUri !== "" &&
    currentHeadlessJwksCache?.jwksUri === trimmedJwksUri
      ? (currentHeadlessJwksCache.parsedKeys ?? [])
      : [];
  const unsupportedParsedAlgorithms = parsedKeysForCurrentJwksUri
    .map((key, index) => ({
      alg: key.alg?.trim() ?? "",
      label: formatHeadlessParsedKeyLabel(key.kid, index),
    }))
    .filter(
      (entry) =>
        entry.alg !== "" &&
        !HEADLESS_LOGIN_ALLOWED_ALGORITHM_SET.has(entry.alg),
    );
  const missingParsedAlgorithms = parsedKeysForCurrentJwksUri
    .map((key, index) => ({
      alg: key.alg?.trim() ?? "",
      label: formatHeadlessParsedKeyLabel(key.kid, index),
    }))
    .filter((entry) => entry.alg === "");
  const unsupportedParsedAlgorithmSummary = unsupportedParsedAlgorithms
    .map((entry) => `${entry.label}: ${entry.alg}`)
    .join(", ");
  const missingParsedAlgorithmSummary = missingParsedAlgorithms
    .map((entry) => entry.label)
    .join(", ");
  const allowedHeadlessAlgorithmsTooltip = t(
    "msg.dev.clients.general.public_key.allowed_algorithms_tooltip",
    "허용 알고리즘: {{algorithms}}",
    { algorithms: HEADLESS_LOGIN_ALLOWED_ALGORITHMS.join(", ") },
  );

  if (headlessLoginEnabled) {
    if (!trimmedJwksUri) {
      validationErrors.push(
        t(
          "msg.dev.clients.general.public_key.validation.missing_jwks_uri",
          "JWKS URI를 입력해야 합니다.",
        ),
      );
    } else if (!isValidUrl(trimmedJwksUri)) {
      validationErrors.push(
        t(
          "msg.dev.clients.general.public_key.validation.invalid_jwks_uri",
          "JWKS URI 형식이 올바르지 않습니다.",
        ),
      );
    }
    if (unsupportedParsedAlgorithms.length > 0) {
      validationErrors.push(
        t(
          "msg.dev.clients.general.public_key.validation.unsupported_parsed_algorithms",
          "JWKS에 지원하지 않는 알고리즘이 있습니다: {{details}}",
          { details: unsupportedParsedAlgorithmSummary },
        ),
      );
    }
    if (missingParsedAlgorithms.length > 0) {
      validationErrors.push(
        t(
          "msg.dev.clients.general.public_key.validation.missing_parsed_algorithms",
          "JWKS에 알고리즘(`alg`)이 선언되지 않은 키가 있습니다: {{details}}",
          { details: missingParsedAlgorithmSummary },
        ),
      );
    }
  }

  const hasValidationErrors = validationErrors.length > 0;

  const refreshHeadlessJwksCacheMutation = useMutation({
    mutationFn: async () => {
      if (!clientId) throw new Error("Missing client id");
      return refreshHeadlessJwksCache(clientId);
    },
    onSuccess: (result) => {
      if (clientId) {
        queryClient.setQueryData(["client", clientId], result);
        queryClient.invalidateQueries({ queryKey: ["client", clientId] });
      }
      toast(
        t(
          "msg.dev.clients.general.public_key.cache_refreshed",
          "JWKS 캐시를 새로 고쳤습니다.",
        ),
      );
    },
    onError: (err) => {
      const errorMessage =
        (err as AxiosError<{ error?: string }>).response?.data?.error ??
        (err as Error)?.message ??
        t("msg.common.unknown_error", "unknown error");
      toast(
        t(
          "msg.dev.clients.general.public_key.cache_refresh_failed",
          "JWKS 캐시 새로고침에 실패했습니다: {{error}}",
          { error: errorMessage },
        ),
      );
    },
  });

  const revokeHeadlessJwksCacheMutation = useMutation({
    mutationFn: async () => {
      if (!clientId) throw new Error("Missing client id");
      return revokeHeadlessJwksCache(clientId);
    },
    onSuccess: () => {
      if (clientId) {
        queryClient.invalidateQueries({ queryKey: ["client", clientId] });
      }
      toast(
        t(
          "msg.dev.clients.general.public_key.cache_revoked",
          "JWKS 캐시를 삭제했습니다.",
        ),
      );
    },
    onError: (err) => {
      const errorMessage =
        (err as AxiosError<{ error?: string }>).response?.data?.error ??
        (err as Error)?.message ??
        t("msg.common.unknown_error", "unknown error");
      toast(
        t(
          "msg.dev.clients.general.public_key.cache_revoke_failed",
          "JWKS 캐시 삭제에 실패했습니다: {{error}}",
          { error: errorMessage },
        ),
      );
    },
  });

  const mutation = useMutation({
    mutationFn: async () => {
      if (hasLogoUrl && !hasValidLogoUrl) {
        throw new Error(
          t(
            "msg.dev.clients.general.identity.logo_invalid",
            "앱 로고 URL 형식이 올바르지 않습니다. http 또는 https 주소를 입력하세요.",
          ),
        );
      }

      const scopeNames = scopes.map((scope) => scope.name).filter(Boolean);

      const effectiveTokenEndpointAuthMethod =
        clientType === "pkce" && headlessLoginEnabled
          ? "none"
          : tokenEndpointAuthMethod;

      const payload: ClientUpsertRequest = {
        name,
        type: clientType,
        scopes: scopeNames,
        tokenEndpointAuthMethod: effectiveTokenEndpointAuthMethod,
        jwksUri:
          effectiveTokenEndpointAuthMethod === "private_key_jwt" &&
          trimmedJwksUri
            ? trimmedJwksUri
            : undefined,
        metadata: {
          description,
          logo_url: trimmedLogoUrl,
          structured_scopes: scopes,
          token_endpoint_auth_method: effectiveTokenEndpointAuthMethod,
          headless_login_enabled: headlessLoginEnabled,
          headless_token_endpoint_auth_method:
            clientType === "pkce" && headlessLoginEnabled
              ? tokenEndpointAuthMethod
              : undefined,
          headless_jwks_uri:
            clientType === "pkce" && headlessLoginEnabled
              ? trimmedJwksUri
              : undefined,
        },
      };

      if (isCreate) {
        payload.status = status;
        payload.redirectUris = redirectUris
          .split(",")
          .map((uri) => uri.trim())
          .filter(Boolean);
        return createClient(payload);
      }

      const updated = await updateClient(clientId as string, payload);
      if (status !== initialStatus) {
        await updateClientStatus(clientId as string, status);
      }
      return updated;
    },
    onSuccess: (result) => {
      queryClient.invalidateQueries({ queryKey: ["clients"] });
      if (status !== initialStatus) {
        setInitialStatus(status);
      }
      if (result?.client?.id) {
        navigate(`/clients/${result.client.id}/settings`);
      }
      alert(t("msg.dev.clients.general.saved", "설정이 저장되었습니다."));
    },
    onError: (err) => {
      const errorMessage =
        (err as AxiosError<{ error?: string }>).response?.data?.error ??
        (err as Error)?.message ??
        t("msg.common.unknown_error", "unknown error");
      alert(
        t(
          "msg.dev.clients.general.save_error",
          "저장에 실패했습니다: {{error}}",
          {
            error: errorMessage,
          },
        ),
      );
    },
  });

  const deleteMutation = useMutation({
    mutationFn: (id: string) => deleteClient(id),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ["clients"] });
      alert(t("msg.dev.clients.deleted", "앱이 삭제되었습니다."));
      navigate("/clients");
    },
    onError: (err) => {
      const errorMessage =
        (err as AxiosError<{ error?: string }>).response?.data?.error ??
        (err as Error)?.message;
      alert(
        t("msg.dev.clients.delete_error", "삭제 실패: {{error}}", {
          error: errorMessage,
        }),
      );
    },
  });

  const handleDelete = () => {
    if (
      clientId &&
      window.confirm(
        t(
          "msg.dev.clients.delete_confirm",
          "정말로 이 앱을 삭제하시습니까? 이 작업은 되돌릴 수 없습니다.",
        ),
      )
    ) {
      deleteMutation.mutate(clientId);
    }
  };

  if (!isCreate && isLoading) {
    return (
      <div className="p-8 text-center">
        {t("msg.dev.clients.general.loading", "Loading client...")}
      </div>
    );
  }
  if (!isCreate && (error || !data)) {
    const errMsg =
      (error as AxiosError<{ error?: string }>).response?.data?.error ??
      (error as Error)?.message;
    return (
      <div className="p-8 text-center text-red-500">
        {t(
          "msg.dev.clients.general.load_error",
          "Error loading client: {{error}}",
          {
            error: errMsg || t("msg.common.unknown_error", "unknown error"),
          },
        )}
      </div>
    );
  }

  const publicKeyStatusTone = headlessLoginEnabled
    ? hasValidationErrors
      ? "border-destructive/40 bg-destructive/5"
      : "border-primary/30 bg-primary/5"
    : "border-border bg-muted/20";

  const displayName = isCreate
    ? t("ui.dev.clients.general.display_new", "새 클라이언트")
    : data?.client?.name || data?.client?.id;

  return (
    <div className="space-y-8">
      <header className="space-y-4">
        <div className="flex flex-wrap items-start justify-between gap-4">
          <div className="space-y-2">
            <nav className="flex flex-wrap items-center gap-2 text-sm text-muted-foreground">
              <Link to="/" className="hover:text-primary">
                {t("ui.dev.clients.consents.breadcrumb.home", "Home")}
              </Link>
              <span>/</span>
              <Link to="/clients" className="hover:text-primary">
                {t("ui.dev.clients.consents.breadcrumb.clients", "Apps")}
              </Link>
              <span>/</span>
              <span>{displayName}</span>
              {!isCreate && (
                <>
                  <span>/</span>
                  <span className="text-foreground font-semibold">
                    {t("ui.dev.clients.details.tab.settings", "Settings")}
                  </span>
                </>
              )}
            </nav>
            <div className="flex items-center gap-2">
              <Button variant="ghost" size="icon" asChild>
                <Link to={isCreate ? "/clients" : `/clients/${clientId}`}>
                  <ArrowLeft className="h-4 w-4" />
                </Link>
              </Button>
              <div>
                <h1 className="text-3xl font-black leading-tight">
                  {isCreate
                    ? t("ui.dev.clients.general.title_create", "Create Client")
                    : t("ui.dev.clients.general.title_edit", "Client Settings")}
                </h1>
                <p className="text-muted-foreground">
                  {t(
                    "ui.dev.clients.general.subtitle",
                    "앱 정보, 권한 스코프, 보안 설정을 관리합니다.",
                  )}
                </p>
              </div>
            </div>
          </div>
          {!isCreate && (
            <Badge
              variant={status === "active" ? "info" : "muted"}
              className="px-3 py-1 text-xs uppercase"
            >
              {status === "active"
                ? t("ui.common.status.active", "Active")
                : t("ui.common.status.inactive", "Inactive")}
            </Badge>
          )}
        </div>
        <div className="flex gap-6 overflow-x-auto border-b border-border pb-3 text-sm font-bold">
          {!isCreate && (
            <>
              <Link
                to={`/clients/${clientId}`}
                className="whitespace-nowrap border-b-2 border-transparent text-muted-foreground hover:text-foreground"
              >
                {t("ui.dev.clients.details.tab.connection", "Federation")}
              </Link>
              <Link
                to={`/clients/${clientId}/consents`}
                className="whitespace-nowrap border-b-2 border-transparent text-muted-foreground hover:text-foreground"
              >
                {t("ui.dev.clients.details.tab.consents", "Consent & Users")}
              </Link>
              <span className="whitespace-nowrap border-b-2 border-primary pb-1 text-primary">
                {t("ui.dev.clients.details.tab.settings", "Settings")}
              </span>
            </>
          )}
        </div>
      </header>

      {/* 1. Application Identity */}
      <div className="glass-panel p-6">
        <div className="flex items-center justify-between mb-6">
          <div>
            <CardTitle className="text-xl font-bold mb-2">
              {t(
                "ui.dev.clients.general.identity.title",
                "Application Identity",
              )}
            </CardTitle>
            <CardDescription>
              {t(
                "msg.dev.clients.general.identity.subtitle",
                "앱 이름과 설명, 로고를 설정합니다.",
              )}
            </CardDescription>
          </div>
        </div>
        <div className="grid gap-8 md:grid-cols-2">
          <div className="space-y-5">
            <div className="space-y-2">
              <Label className="text-sm font-semibold">
                {t("ui.dev.clients.general.identity.name", "앱 이름")}{" "}
                <span className="text-destructive">*</span>
              </Label>
              <Input
                value={name}
                onChange={(e) => setName(e.target.value)}
                placeholder={t(
                  "ui.dev.clients.general.identity.name_placeholder",
                  "My Awesome Application",
                )}
              />
            </div>
            <div className="space-y-2">
              <Label className="text-sm font-semibold">
                {t(
                  "ui.dev.clients.general.identity.description",
                  "Description",
                )}
              </Label>
              <Textarea
                rows={3}
                value={description}
                onChange={(e) => setDescription(e.target.value)}
                placeholder={t(
                  "ui.dev.clients.general.identity.description_placeholder",
                  "앱에 대한 간단한 설명을 입력하세요.",
                )}
              />
            </div>
          </div>
          <div className="space-y-5">
            <div className="space-y-2">
              <Label className="text-sm font-semibold">
                {t("ui.dev.clients.general.identity.logo", "App Logo URL")}
              </Label>
              <div className="flex gap-4">
                <div className="flex-1 space-y-2">
                  <Input
                    value={logoUrl}
                    onChange={(e) => setLogoUrl(e.target.value)}
                    aria-invalid={!hasValidLogoUrl}
                    className={!hasValidLogoUrl ? "border-destructive" : ""}
                    placeholder={t(
                      "ui.dev.clients.general.identity.logo_placeholder",
                      "https://example.com/logo.png",
                    )}
                  />
                  <p className="text-xs text-muted-foreground">
                    {t(
                      "msg.dev.clients.general.identity.logo_help",
                      "인증 화면에 표시될 PNG/SVG URL입니다.",
                    )}
                  </p>
                  {!hasValidLogoUrl ? (
                    <p className="text-xs text-destructive">
                      {t(
                        "msg.dev.clients.general.identity.logo_invalid",
                        "앱 로고 URL 형식이 올바르지 않습니다. http 또는 https 주소를 입력하세요.",
                      )}
                    </p>
                  ) : null}
                  {hasLogoUrl && hasValidLogoUrl ? (
                    <div className="flex items-center gap-2 text-xs">
                      <span
                        className={cn("text-muted-foreground", {
                          "text-foreground": logoPreviewStatus === "loaded",
                          "text-destructive": logoPreviewStatus === "error",
                        })}
                      >
                        {logoPreviewStatus === "loading"
                          ? t(
                              "msg.dev.clients.general.identity.logo_preview_loading",
                              "로고 미리보기를 불러오는 중입니다.",
                            )
                          : logoPreviewStatus === "loaded"
                            ? t(
                                "msg.dev.clients.general.identity.logo_preview_ready",
                                "로고 미리보기를 확인했습니다.",
                              )
                            : logoPreviewStatus === "error"
                              ? t(
                                  "msg.dev.clients.general.identity.logo_preview_failed",
                                  "로고 미리보기를 불러오지 못했습니다. URL 또는 이미지 접근 권한을 확인하세요.",
                                )
                              : null}
                      </span>
                      <a
                        href={trimmedLogoUrl}
                        target="_blank"
                        rel="noreferrer"
                        className="inline-flex items-center gap-1 text-muted-foreground underline-offset-4 hover:text-foreground hover:underline"
                      >
                        <ExternalLink className="h-3 w-3" />
                        {t(
                          "ui.dev.clients.general.identity.logo_open",
                          "새 탭에서 열기",
                        )}
                      </a>
                    </div>
                  ) : null}
                </div>
                <div
                  className={cn(
                    "flex h-20 w-20 shrink-0 items-center justify-center rounded-lg border-2 border-dashed",
                    hasLogoUrl &&
                      hasValidLogoUrl &&
                      logoPreviewStatus !== "error"
                      ? "bg-white"
                      : "bg-muted/40",
                    logoPreviewStatus === "error"
                      ? "border-destructive/60"
                      : "border-border",
                  )}
                >
                  {hasLogoUrl && hasValidLogoUrl ? (
                    <img
                      key={trimmedLogoUrl}
                      src={trimmedLogoUrl}
                      alt={t(
                        "ui.dev.clients.general.identity.logo_preview",
                        "Logo Preview",
                      )}
                      className="h-full w-full object-contain"
                      onLoad={() => setLogoPreviewStatus("loaded")}
                      onError={() => setLogoPreviewStatus("error")}
                    />
                  ) : (
                    <div className="flex flex-col items-center justify-center gap-1 px-2 text-center">
                      <Upload
                        className={cn("h-5 w-5 text-muted-foreground", {
                          "text-destructive": logoPreviewStatus === "error",
                        })}
                      />
                      {logoPreviewStatus === "error" ? (
                        <span className="text-[10px] leading-tight text-destructive">
                          {t(
                            "ui.dev.clients.general.identity.logo_preview_error_badge",
                            "미리보기 실패",
                          )}
                        </span>
                      ) : (
                        <span className="text-[10px] leading-tight text-muted-foreground">
                          {t(
                            "ui.dev.clients.general.identity.logo_preview_empty",
                            "미리보기",
                          )}
                        </span>
                      )}
                    </div>
                  )}
                </div>
              </div>
            </div>

            <div className="space-y-2">
              <Label className="text-sm font-semibold">
                {t("ui.dev.clients.table.status", "상태")}
              </Label>
              <div className="flex gap-2">
                <Button
                  type="button"
                  size="sm"
                  variant={status === "active" ? "default" : "outline"}
                  onClick={() => handleStatusChange("active")}
                >
                  {t("ui.common.status.active", "활성")}
                </Button>
                <Button
                  type="button"
                  size="sm"
                  variant={status === "inactive" ? "default" : "outline"}
                  onClick={() => handleStatusChange("inactive")}
                >
                  {t("ui.common.status.inactive", "비활성")}
                </Button>
              </div>
            </div>
          </div>
        </div>
      </div>

      {/* 2. Scopes */}
      <Card className="glass-panel">
        <CardHeader className="flex flex-row items-center justify-between space-y-0 pb-4">
          <div>
            <CardTitle className="text-xl font-bold">
              {t("ui.dev.clients.general.scopes.title", "Scopes")}
            </CardTitle>
            <CardDescription>
              {t(
                "msg.dev.clients.general.scopes.subtitle",
                "이 클라이언트가 요청할 수 있는 권한 범위를 정의합니다.",
              )}
            </CardDescription>
          </div>
          <Button
            variant="outline"
            size="sm"
            onClick={addScope}
            className="gap-2"
          >
            <Plus className="h-4 w-4" />
            {t("ui.dev.clients.general.scopes.add", "Scope 추가")}
          </Button>
        </CardHeader>
        <CardContent className="space-y-6">
          {isCreate && (
            <div className="space-y-2 border-b border-border pb-6 mb-6">
              <Label className="text-sm font-semibold">
                {t("ui.dev.clients.general.redirect.label", "Redirect URIs")}{" "}
                <span className="text-destructive">*</span>
              </Label>
              <Textarea
                value={redirectUris}
                onChange={(e) => setRedirectUris(e.target.value)}
                placeholder={t(
                  "ui.dev.clients.general.redirect.placeholder",
                  "https://app.example.com/callback, http://localhost:3000/auth/callback (콤마로 구분)",
                )}
                className="font-mono text-sm"
              />
              <p className="text-xs text-muted-foreground">
                {t(
                  "msg.dev.clients.general.redirect.help",
                  "인증 후 리다이렉트될 URI를 입력하세요. 생성 후 Connection 탭에서 수정 가능합니다.",
                )}
              </p>
            </div>
          )}

          <div className="rounded-md border border-border overflow-hidden">
            <table className="w-full text-sm">
              <thead className="bg-muted/50 border-b border-border text-xs uppercase tracking-wider text-muted-foreground">
                <tr>
                  <th className="px-4 py-3 text-left font-bold">
                    {t(
                      "ui.dev.clients.general.scopes.table.name",
                      "Scope Name",
                    )}
                  </th>
                  <th className="px-4 py-3 text-left font-bold">
                    {t(
                      "ui.dev.clients.general.scopes.table.description",
                      "Description",
                    )}
                  </th>
                  <th className="px-4 py-3 text-center font-bold">
                    {t(
                      "ui.dev.clients.general.scopes.table.mandatory",
                      "Mandatory",
                    )}
                  </th>
                  <th className="px-4 py-3 text-right font-bold">
                    {t("ui.dev.clients.general.scopes.table.delete", "Delete")}
                  </th>
                </tr>
              </thead>
              <tbody className="divide-y divide-border">
                {scopes.map((s) => (
                  <tr
                    key={s.id}
                    className="hover:bg-muted/30 transition-colors"
                  >
                    <td className="px-4 py-3">
                      <Input
                        value={s.name}
                        onChange={(e) =>
                          updateScope(s.id, "name", e.target.value)
                        }
                        className="h-8 font-mono text-xs"
                        placeholder={t(
                          "ui.dev.clients.general.scopes.name_placeholder",
                          "e.g. profile",
                        )}
                      />
                    </td>
                    <td className="px-4 py-3">
                      <Input
                        value={s.description}
                        onChange={(e) =>
                          updateScope(s.id, "description", e.target.value)
                        }
                        className="h-8 text-xs"
                        placeholder={t(
                          "ui.dev.clients.general.scopes.description_placeholder",
                          "권한에 대한 설명",
                        )}
                      />
                    </td>
                    <td className="px-4 py-3 text-center">
                      <div className="flex justify-center">
                        <Switch
                          checked={s.mandatory}
                          onCheckedChange={(checked) =>
                            updateScope(s.id, "mandatory", checked)
                          }
                        />
                      </div>
                    </td>
                    <td className="px-4 py-3 text-right">
                      <Button
                        variant="ghost"
                        size="icon"
                        onClick={() => removeScope(s.id)}
                        className="h-8 w-8 text-muted-foreground hover:text-destructive"
                      >
                        <Trash2 className="h-4 w-4" />
                      </Button>
                    </td>
                  </tr>
                ))}
                {scopes.length === 0 && (
                  <tr>
                    <td
                      colSpan={4}
                      className="px-4 py-8 text-center text-muted-foreground"
                    >
                      {t(
                        "msg.dev.clients.general.scopes.empty",
                        "등록된 스코프가 없습니다.",
                      )}
                    </td>
                  </tr>
                )}
              </tbody>
            </table>
          </div>
        </CardContent>
      </Card>

      {/* 3. Security Settings */}
      <Card className="glass-panel">
        <CardHeader className="pb-3">
          <CardTitle className="text-xl font-bold">
            {t("ui.dev.clients.general.security.title", "보안 설정")}
          </CardTitle>
          <CardDescription>
            {t(
              "msg.dev.clients.general.security.subtitle",
              "클라이언트 유형을 선택하세요. 보안 수준에 따라 인증 방식이 달라집니다.",
            )}
          </CardDescription>
        </CardHeader>
        <CardContent className="space-y-4">
          <div className="grid gap-4 md:grid-cols-2">
            <label
              className={cn(
                "relative flex cursor-pointer flex-col gap-1 rounded-xl border-2 p-4 transition",
                securityProfile === "private"
                  ? "border-primary bg-primary/5"
                  : "border-border bg-card hover:border-muted-foreground/40",
              )}
            >
              <input
                className="sr-only"
                type="radio"
                name="security-profile"
                checked={securityProfile === "private"}
                onChange={() => handleSecurityProfileChange("private")}
              />
              <span className="flex items-center gap-2 text-sm font-bold uppercase text-foreground">
                <Shield className="h-4 w-4 text-primary" />
                {t(
                  "ui.dev.clients.general.security.private",
                  "Server side App",
                )}
              </span>
              <span className="text-xs text-muted-foreground">
                {t(
                  "msg.dev.clients.general.security.private_help",
                  "서버 사이드 앱(예: Node.js, Java)처럼 비밀키를 안전하게 보관 가능한 경우.",
                )}
              </span>
              <span className="absolute right-4 top-4 text-primary">
                {securityProfile === "private" ? "✓" : ""}
              </span>
            </label>

            <label
              className={cn(
                "relative flex cursor-pointer flex-col gap-1 rounded-xl border-2 p-4 transition",
                securityProfile === "pkce"
                  ? "border-primary bg-primary/5"
                  : "border-border bg-card hover:border-muted-foreground/40",
              )}
            >
              <input
                className="sr-only"
                type="radio"
                name="security-profile"
                checked={securityProfile === "pkce"}
                onChange={() => handleSecurityProfileChange("pkce")}
              />
              <span className="flex items-center gap-2 text-sm font-bold uppercase text-foreground">
                <Sparkles className="h-4 w-4" />
                {t("ui.dev.clients.general.security.pkce", "PKCE")}
              </span>
              <span className="text-xs text-muted-foreground">
                {t(
                  "msg.dev.clients.general.security.pkce_help",
                  "SPA/모바일 앱처럼 비밀키 보관이 어려운 경우. PKCE를 기본 사용합니다.",
                )}
              </span>
              <span className="absolute right-4 top-4 text-primary">
                {securityProfile === "pkce" ? "✓" : ""}
              </span>

              {securityProfile === "pkce" && (
                <fieldset
                  className="mt-4 pt-4 border-t border-primary/20 flex items-center justify-between"
                  onClick={(e) => e.stopPropagation()}
                  onKeyDown={(e) => e.stopPropagation()}
                >
                  <div className="space-y-0.5">
                    <Label
                      className="text-xs font-bold cursor-pointer"
                      htmlFor="headless-login-toggle"
                    >
                      {t(
                        "ui.dev.clients.general.security.headless_login_enable",
                        "Headless Login (자체 로그인 UI 사용)",
                      )}
                    </Label>
                    <p className="text-[10px] text-muted-foreground">
                      {t(
                        "ui.dev.clients.general.security.headless_login_enable_help",
                        "Baron SSO 로그인 창을 거치지 않고 애플리케이션 내의 자체 로그인 화면을 직접 구현하고 싶은 경우 활성화합니다.",
                      )}
                    </p>
                  </div>
                  <Switch
                    id="headless-login-toggle"
                    checked={headlessLoginEnabled}
                    onCheckedChange={handleHeadlessToggle}
                  />
                </fieldset>
              )}
            </label>
          </div>
        </CardContent>
      </Card>

      {/* 4. Public Key Registration (Headless Login) */}
      {clientType === "pkce" && headlessLoginEnabled && (
        <Card className="glass-panel border-primary/20">
          <CardHeader className="pb-3">
            <div className="flex flex-wrap items-start justify-between gap-3">
              <div>
                <CardTitle className="text-xl font-bold flex items-center gap-2">
                  {t(
                    "ui.dev.clients.general.public_key.title",
                    "Public Key Registration",
                  )}
                </CardTitle>
                <CardDescription>
                  {t(
                    "msg.dev.clients.general.public_key.subtitle",
                    "Headless Login 판정에 필요한 공개키와 관련 설정을 관리합니다.",
                  )}
                </CardDescription>
              </div>
            </div>
          </CardHeader>
          <CardContent className="space-y-6">
            <div className={cn("rounded-xl border p-4", publicKeyStatusTone)}>
              <div className="flex items-center justify-between">
                <div>
                  <Label className="text-sm font-bold text-foreground">
                    {t(
                      "ui.dev.clients.general.public_key.headless_toggle",
                      "Headless Login 허용 여부",
                    )}
                  </Label>
                  <p className="mt-1 text-xs text-muted-foreground">
                    {t(
                      "msg.dev.clients.general.public_key.headless_help",
                      "애플리케이션 고유의 디자인으로 로그인 화면을 구성할 수 있습니다. 실제 아이디/비밀번호 확인 및 보안 검증 로직은 Baron API를 통해 백그라운드에서 처리됩니다.",
                    )}
                  </p>
                </div>
                <Badge
                  variant="default"
                  className="bg-primary/20 text-primary border-primary/30"
                >
                  {t("ui.common.enabled", "Enabled")}
                </Badge>
              </div>
            </div>

            <div className="space-y-4">
              <div className="space-y-3 rounded-xl border border-border bg-muted/5 p-4">
                <div className="space-y-2">
                  <div className="flex items-center gap-2">
                    <Label className="text-sm font-semibold" htmlFor="jwks-uri">
                      {t(
                        "ui.dev.clients.general.public_key.jwks_uri",
                        "JWKS URI",
                      )}
                      <span className="text-destructive ml-1">*</span>
                    </Label>
                    <Button
                      type="button"
                      variant="ghost"
                      size="icon"
                      className="h-7 w-7 text-muted-foreground"
                      title={allowedHeadlessAlgorithmsTooltip}
                      aria-label={t(
                        "ui.dev.clients.general.public_key.allowed_algorithms_info",
                        "Headless Login 허용 알고리즘 정보",
                      )}
                    >
                      <Info className="h-4 w-4" />
                    </Button>
                  </div>
                  <Input
                    id="jwks-uri"
                    value={jwksUri}
                    onChange={(e) => setJwksUri(e.target.value)}
                    placeholder={t(
                      "ui.dev.clients.general.public_key.jwks_uri_placeholder",
                      "https://rp.example.com/.well-known/jwks.json",
                    )}
                  />
                  <p className="text-xs text-muted-foreground">
                    {t(
                      "msg.dev.clients.general.public_key.jwks_uri_help",
                      "RP backend가 제공하는 공개키 endpoint URL을 입력하세요.",
                    )}
                  </p>
                </div>
              </div>

              <div className="space-y-3 rounded-xl border border-border bg-card p-4">
                <div className="flex flex-wrap items-start justify-between gap-3">
                  <div>
                    <Label className="text-sm font-bold">
                      {t(
                        "ui.dev.clients.general.public_key.cache.title",
                        "JWKS Cache",
                      )}
                    </Label>
                    <p className="mt-1 text-xs text-muted-foreground">
                      {t(
                        "msg.dev.clients.general.public_key.cache_help",
                        "백엔드가 마지막으로 검증한 공개키 캐시 상태입니다.",
                      )}
                    </p>
                  </div>
                  <div className="flex gap-2">
                    <Button
                      type="button"
                      size="sm"
                      variant="outline"
                      onClick={() => refreshHeadlessJwksCacheMutation.mutate()}
                      disabled={refreshHeadlessJwksCacheMutation.isPending}
                    >
                      {refreshHeadlessJwksCacheMutation.isPending
                        ? t("msg.common.requesting", "요청 중...")
                        : t("ui.common.refresh", "Refresh")}
                    </Button>
                    <Button
                      type="button"
                      size="sm"
                      variant="destructive"
                      onClick={() => {
                        if (
                          !currentHeadlessJwksCache ||
                          revokeHeadlessJwksCacheMutation.isPending
                        ) {
                          return;
                        }
                        const confirmed = window.confirm(
                          t(
                            "msg.dev.clients.general.public_key.cache_revoke_confirm",
                            "JWKS 캐시를 삭제하면 다음 검증 전에 다시 갱신해야 합니다. 계속할까요?",
                          ),
                        );
                        if (confirmed) {
                          revokeHeadlessJwksCacheMutation.mutate();
                        }
                      }}
                      disabled={
                        !currentHeadlessJwksCache ||
                        revokeHeadlessJwksCacheMutation.isPending
                      }
                    >
                      {revokeHeadlessJwksCacheMutation.isPending
                        ? t("msg.common.requesting", "요청 중...")
                        : t(
                            "ui.dev.clients.general.public_key.revoke_cache",
                            "Revoke Cache",
                          )}
                    </Button>
                  </div>
                </div>

                {currentHeadlessJwksCache ? (
                  <div className="grid gap-3 text-sm md:grid-cols-2">
                    <div className="space-y-1">
                      <p className="text-xs font-semibold uppercase text-muted-foreground">
                        {t(
                          "ui.dev.clients.general.public_key.cache.status",
                          "Status",
                        )}
                      </p>
                      <Badge variant="info" className="w-fit capitalize">
                        {currentHeadlessJwksCache.lastRefreshStatus ||
                          t("ui.common.unknown", "Unknown")}
                      </Badge>
                    </div>
                    <div className="space-y-1">
                      <p className="text-xs font-semibold uppercase text-muted-foreground">
                        {t(
                          "ui.dev.clients.general.public_key.cache.uri",
                          "JWKS URI",
                        )}
                      </p>
                      <p className="break-all font-mono text-xs">
                        {currentHeadlessJwksCache.jwksUri}
                      </p>
                    </div>
                    <div className="space-y-1">
                      <p className="text-xs font-semibold uppercase text-muted-foreground">
                        {t(
                          "ui.dev.clients.general.public_key.cache.cached_at",
                          "Cached At",
                        )}
                      </p>
                      <p>{formatDateTime(currentHeadlessJwksCache.cachedAt)}</p>
                    </div>
                    <div className="space-y-1">
                      <p className="text-xs font-semibold uppercase text-muted-foreground">
                        {t(
                          "ui.dev.clients.general.public_key.cache.expires_at",
                          "Expires At",
                        )}
                      </p>
                      <p>
                        {formatDateTime(currentHeadlessJwksCache.expiresAt)}
                      </p>
                    </div>
                    <div className="space-y-1">
                      <p className="text-xs font-semibold uppercase text-muted-foreground">
                        {t(
                          "ui.dev.clients.general.public_key.cache.last_checked_at",
                          "Last Checked",
                        )}
                      </p>
                      <p>
                        {formatDateTime(currentHeadlessJwksCache.lastCheckedAt)}
                      </p>
                    </div>
                    <div className="space-y-1">
                      <p className="text-xs font-semibold uppercase text-muted-foreground">
                        {t(
                          "ui.dev.clients.general.public_key.cache.last_success",
                          "Last Successful Verification",
                        )}
                      </p>
                      <p>
                        {formatDateTime(
                          currentHeadlessJwksCache.lastSuccessfulVerificationAt,
                        )}
                      </p>
                    </div>
                    <div className="space-y-1">
                      <p className="text-xs font-semibold uppercase text-muted-foreground">
                        {t(
                          "ui.dev.clients.general.public_key.cache.failures",
                          "Consecutive Failures",
                        )}
                      </p>
                      <p>{currentHeadlessJwksCache.consecutiveFailures ?? 0}</p>
                    </div>
                    <div className="space-y-1">
                      <p className="text-xs font-semibold uppercase text-muted-foreground">
                        {t(
                          "ui.dev.clients.general.public_key.cache.kids",
                          "Cached KIDs",
                        )}
                      </p>
                      <p className="font-mono text-xs">
                        {currentHeadlessJwksCache.cachedKids?.length
                          ? currentHeadlessJwksCache.cachedKids.join(", ")
                          : "-"}
                      </p>
                    </div>
                    <div className="space-y-1 md:col-span-2">
                      <p className="text-xs font-semibold uppercase text-muted-foreground">
                        {t(
                          "ui.dev.clients.general.public_key.cache.error",
                          "Last Error",
                        )}
                      </p>
                      <p className="break-words text-xs text-muted-foreground">
                        {currentHeadlessJwksCache.lastError || "-"}
                      </p>
                    </div>
                    {(unsupportedParsedAlgorithms.length > 0 ||
                      missingParsedAlgorithms.length > 0) && (
                      <div className="space-y-2 rounded-lg border border-destructive/40 bg-destructive/5 p-3 md:col-span-2">
                        <p className="text-sm font-semibold text-destructive">
                          {unsupportedParsedAlgorithms.length > 0
                            ? t(
                                "msg.dev.clients.general.public_key.cache.unsupported_algorithms_title",
                                "지원하지 않는 알고리즘이 감지되었습니다.",
                              )
                            : t(
                                "msg.dev.clients.general.public_key.cache.missing_algorithms_title",
                                "알고리즘이 선언되지 않았습니다.",
                              )}
                        </p>
                        <p className="text-xs text-destructive">
                          {unsupportedParsedAlgorithms.length > 0
                            ? t(
                                "msg.dev.clients.general.public_key.cache.unsupported_algorithms_help",
                                "저장 전 JWKS를 수정해 주세요: {{details}}",
                                { details: unsupportedParsedAlgorithmSummary },
                              )
                            : t(
                                "msg.dev.clients.general.public_key.cache.missing_algorithms_help",
                                "저장 전 JWKS 각 키에 `alg`를 명시해 주세요: {{details}}",
                                { details: missingParsedAlgorithmSummary },
                              )}
                        </p>
                      </div>
                    )}
                    <div className="space-y-3 md:col-span-2">
                      <div className="flex items-center justify-between gap-2">
                        <p className="text-xs font-semibold uppercase text-muted-foreground">
                          {t(
                            "ui.dev.clients.general.public_key.cache.parsed_keys",
                            "Parsed Keys",
                          )}
                        </p>
                        <p className="text-[11px] text-muted-foreground">
                          {t(
                            "msg.dev.clients.general.public_key.cache.parsed_keys_help",
                            "Raw JWKS stays hidden. Only parsed key metadata is shown here.",
                          )}
                        </p>
                      </div>
                      {currentHeadlessJwksCache.parsedKeys?.length ? (
                        <div className="space-y-3">
                          {currentHeadlessJwksCache.parsedKeys.map((key) => {
                            const normalizedAlgorithm = key.alg?.trim() ?? "";
                            const isMissingAlgorithm =
                              normalizedAlgorithm === "";
                            const isUnsupportedAlgorithm =
                              !isMissingAlgorithm &&
                              !HEADLESS_LOGIN_ALLOWED_ALGORITHM_SET.has(
                                normalizedAlgorithm,
                              );

                            return (
                              <div
                                key={`${key.kid ?? "missing-kid"}-${key.kty ?? ""}-${key.alg ?? ""}-${key.n ?? ""}`}
                                className={cn(
                                  "rounded-xl border bg-muted/30 p-3",
                                  isUnsupportedAlgorithm || isMissingAlgorithm
                                    ? "border-destructive/50 bg-destructive/5"
                                    : "border-border",
                                )}
                              >
                                <div className="grid gap-3 md:grid-cols-2 xl:grid-cols-4">
                                  <div className="space-y-1">
                                    <p className="text-[11px] font-semibold uppercase text-muted-foreground">
                                      KID
                                    </p>
                                    <p className="break-all rounded-lg border border-border bg-background px-3 py-2 font-mono text-[11px]">
                                      {key.kid || "-"}
                                    </p>
                                  </div>
                                  <div className="space-y-1">
                                    <p className="text-[11px] font-semibold uppercase text-muted-foreground">
                                      KTY
                                    </p>
                                    <p className="break-all rounded-lg border border-border bg-background px-3 py-2 font-mono text-[11px]">
                                      {key.kty || "-"}
                                    </p>
                                  </div>
                                  <div className="space-y-1">
                                    <p className="text-[11px] font-semibold uppercase text-muted-foreground">
                                      USE
                                    </p>
                                    <p className="break-all rounded-lg border border-border bg-background px-3 py-2 font-mono text-[11px]">
                                      {key.use || "-"}
                                    </p>
                                  </div>
                                  <div className="space-y-1">
                                    <p className="text-[11px] font-semibold uppercase text-muted-foreground">
                                      ALG
                                    </p>
                                    <p
                                      className={cn(
                                        "break-all rounded-lg border bg-background px-3 py-2 font-mono text-[11px]",
                                        isUnsupportedAlgorithm ||
                                          isMissingAlgorithm
                                          ? "border-destructive/50 text-destructive"
                                          : "border-border",
                                      )}
                                    >
                                      {key.alg ||
                                        t(
                                          "msg.dev.clients.general.public_key.cache.missing_algorithm_badge",
                                          "알고리즘 미선언",
                                        )}
                                    </p>
                                    {isMissingAlgorithm && (
                                      <p className="text-[11px] text-destructive">
                                        {t(
                                          "msg.dev.clients.general.public_key.cache.missing_algorithm_reason",
                                          "이 키는 `alg`가 비어 있어서 저장할 수 없습니다.",
                                        )}
                                      </p>
                                    )}
                                    {isUnsupportedAlgorithm && (
                                      <p className="text-[11px] text-destructive">
                                        {t(
                                          "msg.dev.clients.general.public_key.cache.unsupported_algorithm_reason",
                                          "이 알고리즘은 Headless Login에서 지원되지 않습니다.",
                                        )}
                                      </p>
                                    )}
                                  </div>
                                </div>
                                <div className="mt-3 space-y-1">
                                  <p className="text-[11px] font-semibold uppercase text-muted-foreground">
                                    {t(
                                      "ui.dev.clients.general.public_key.cache.parsed_key_n",
                                      "N",
                                    )}
                                  </p>
                                  <p className="min-h-16 break-all rounded-lg border border-border bg-background px-3 py-2 font-mono text-[11px] leading-5">
                                    {key.n || "-"}
                                  </p>
                                </div>
                              </div>
                            );
                          })}
                        </div>
                      ) : (
                        <div className="rounded-lg border border-dashed border-border px-4 py-5 text-sm text-muted-foreground">
                          {t(
                            "msg.dev.clients.general.public_key.cache.parsed_keys_empty",
                            "No parsed JWKS keys are available yet.",
                          )}
                        </div>
                      )}
                    </div>
                  </div>
                ) : (
                  <div className="rounded-lg border border-dashed border-border px-4 py-6 text-sm text-muted-foreground">
                    {t(
                      "msg.dev.clients.general.public_key.cache_empty",
                      "아직 캐시된 JWKS가 없습니다. Refresh를 눌러 백엔드 캐시 상태를 조회하세요.",
                    )}
                  </div>
                )}
              </div>
            </div>

            {hasValidationErrors && (
              <div className="rounded-xl border border-destructive/40 bg-destructive/5 p-4 animate-in fade-in">
                <p className="text-sm font-semibold text-destructive flex items-center gap-2">
                  <span>⚠️</span>
                  {t(
                    "ui.dev.clients.general.public_key.validation_title",
                    "저장 전 확인 필요",
                  )}
                </p>
                <ul className="mt-2 list-disc space-y-1 pl-6 text-sm text-destructive">
                  {validationErrors.map((errorMessage) => (
                    <li key={errorMessage}>{errorMessage}</li>
                  ))}
                </ul>
              </div>
            )}
          </CardContent>
        </Card>
      )}

      <div className="flex items-center justify-between border-t border-border pt-4">
        <div>
          {!isCreate && (
            <Button
              variant="destructive"
              className="gap-2"
              onClick={handleDelete}
              disabled={deleteMutation.isPending}
            >
              <Trash2 className="h-4 w-4" />
              {deleteMutation.isPending
                ? t("msg.common.requesting", "요청 중...")
                : t("ui.common.delete", "삭제")}
            </Button>
          )}
        </div>
        <div className="flex flex-col-reverse sm:flex-row sm:justify-end gap-2">
          <Button variant="outline" onClick={() => navigate("/clients")}>
            {t("ui.common.cancel", "취소")}
          </Button>
          <Button
            onClick={() => mutation.mutate()}
            disabled={
              mutation.isPending ||
              isLoading ||
              name.trim() === "" ||
              (isCreate && redirectUris.trim() === "") ||
              hasValidationErrors
            }
            className="shadow-lg shadow-primary/20"
          >
            {mutation.isPending ? (
              <div className="h-4 w-4 border-2 border-white/30 border-t-white rounded-full animate-spin mr-2" />
            ) : (
              <Save size={16} className="mr-2" />
            )}
            {mutation.isPending
              ? t("msg.common.saving", "저장 중...")
              : isCreate
                ? t("ui.dev.clients.general.create", "클라이언트 생성")
                : t("ui.common.save", "저장")}
          </Button>
        </div>
      </div>
    </div>
  );
}

export default ClientGeneralPage;
