"use client";

import { useRouter, useSearchParams } from "next/navigation";
import {
  useEffect,
  useRef,
  useState,
  useTransition,
  type PointerEvent as ReactPointerEvent,
} from "react";
import { BottomToast, type BottomToastNotice } from "@/components/bottom-toast";
import { CloseIconButton } from "@/components/close-icon-button";
import { MailBillingHistoryPanel } from "@/components/mail-billing-history-panel";
import {
  MAIL_GROWTH_PLAN_PRICE_PER_MEMBER,
} from "@/lib/mail-billing";
import {
  buildMailBillingSetupHref,
  type MailBillingHistoryState,
  type MailBillingTab,
} from "@/lib/mail-billing-history";
import {
  MAIL_FREE_PLAN_CARD,
  MAIL_GROWTH_PLAN_CARD,
  MAIL_TEAM_PLAN_CARD,
} from "@/lib/mail-plan-cards";
import type {
  MailBillingCancellationOverview,
  MailBillingCancellationRequestKind,
} from "@/lib/billing-cancellation";
import type { ManagedMailboxMember } from "@/lib/mail-automation";
import type {
  MailBillingHistoryPage,
  MailBillingOverview,
  TossPayBillingProfileStatus,
  TossPaySubscriptionStatus,
} from "@/lib/toss-pay";

type TossBillingModuleProps = {
  billingOverview: MailBillingOverview | null;
  cancellationOverview: MailBillingCancellationOverview | null;
  billingSeatCount: number;
  canManageBilling: boolean;
  currentTab: MailBillingTab;
  estimatedMonthlyCost: number;
  historyPage: MailBillingHistoryPage | null;
  historyState: MailBillingHistoryState;
  isComplimentaryGrowthPlan: boolean;
  managedMembers: ManagedMailboxMember[];
  representativeMailbox: string;
};

type BillingRegisterResponse = {
  ok: true;
  registration: {
    billingKey: string | null;
    checkoutAndroidUri: string | null;
    checkoutIosUri: string | null;
    checkoutUri: string;
    publicBaseUrl: string;
    usesCanonicalPublicBaseUrl: boolean;
  };
};

type BillingSubscriptionActionResponse = {
  ok: true;
  subscription: {
    chargedAmount?: number;
    initialPaymentComplete?: boolean;
    nextChargeAt: string | null;
    status: "active" | "paused";
  };
};

type BillingCancellationActionResponse = {
  cancellation: {
    id: number;
    kind: MailBillingCancellationRequestKind;
    message: string;
    requestedAt?: string;
    revokedAt?: string;
    status?: "completed" | "queued" | "revoked";
    subscriptionStatus: TossPaySubscriptionStatus | null;
  };
  message: string;
  ok: true;
};

type ApiErrorResponse = {
  error?: string;
  message?: string;
};

type BillingUiStateOverride = {
  billingProfileStatus?: TossPayBillingProfileStatus;
  initialPaymentComplete?: boolean;
  nextChargeAt?: string | null;
  subscriptionStatus?: TossPaySubscriptionStatus | null;
};

function formatCurrency(value: number) {
  return `${value.toLocaleString("ko-KR")}원`;
}

function formatDateLabel(value: string | null) {
  if (!value) {
    return "아직 없음";
  }

  const date = new Date(value);
  return `${date.getFullYear()}.${String(date.getMonth() + 1).padStart(2, "0")}.${String(
    date.getDate(),
  ).padStart(2, "0")} ${String(date.getHours()).padStart(2, "0")}:${String(
    date.getMinutes(),
  ).padStart(2, "0")}`;
}

function profileStatusLabel(status: TossPayBillingProfileStatus | null | undefined) {
  if (status === "active") {
    return "등록 완료";
  }

  if (status === "pending") {
    return "인증 대기";
  }

  if (status === "removed") {
    return "해지됨";
  }

  if (status === "failed") {
    return "요청 실패";
  }

  return "미등록";
}

function subscriptionStatusLabel(status: TossPaySubscriptionStatus | null | undefined) {
  if (status === "active") {
    return "정기결제 활성";
  }

  if (status === "paused") {
    return "일시중지";
  }

  if (status === "cancelled") {
    return "해지됨";
  }

  return "시작 전";
}

function paymentInstrumentLabel(
  profile: MailBillingOverview["profile"] | undefined,
) {
  if (!profile || profile.status !== "active" || !profile.billingKey) {
    return "";
  }

  if (profile.payMethod === "CARD") {
    return [profile.cardCompanyName, profile.cardNum4Print ? `•••• ${profile.cardNum4Print}` : ""]
      .filter(Boolean)
      .join(" ");
  }

  if (profile.payMethod === "TOSS_MONEY") {
    return [profile.accountBankName, profile.accountNumberMasked]
      .filter(Boolean)
      .join(" ");
  }

  return "";
}

function paymentMethodSummary(overview: MailBillingOverview | null) {
  const profile = overview?.profile;

  if (!profile) {
    return "아직 등록된 결제수단이 없습니다.";
  }

  if (profile.status === "pending") {
    return "토스 인증 대기 중";
  }

  if (profile.status !== "active" || !profile.billingKey) {
    return "아직 등록된 결제수단이 없습니다.";
  }

  const instrumentLabel = paymentInstrumentLabel(profile);

  if (instrumentLabel) {
    return instrumentLabel;
  }

  return "결제수단 등록 완료";
}

function paymentBrandLabel(profile: MailBillingOverview["profile"] | undefined) {
  if (!profile) {
    return "OFFICIAL PAY";
  }

  if (profile.payMethod === "CARD") {
    return profile.cardCompanyName?.toUpperCase() || "CARD";
  }

  if (profile.payMethod === "TOSS_MONEY") {
    return "TOSS PAY";
  }

  return profile.payMethod || "OFFICIAL PAY";
}

function paymentCardNumber(profile: MailBillingOverview["profile"] | undefined) {
  const lastDigits = profile?.cardNum4Print?.trim() || "0000";
  return `4729 51•• •••• ${lastDigits}`;
}

function paymentHolderName(email: string) {
  const localPart = email.split("@")[0] ?? "";
  const normalized = localPart.replace(/[._-]+/g, " ").trim().toUpperCase();
  return normalized || "OFFICIALMAIL USER";
}

function normalizeApiErrorMessage(payload: ApiErrorResponse, fallback: string) {
  const message = payload.message?.trim() || payload.error?.trim() || fallback;

  if (message === "billing-profile-inactive") {
    return "토스페이 자동결제 수단이 아직 활성화되지 않았습니다.";
  }

  if (message === "user-not-found") {
    return "세션 계정을 찾을 수 없습니다.";
  }

  if (message === "billing-cancellation-kind-invalid") {
    return "취소 요청 방식이 올바르지 않습니다.";
  }

  if (message === "billing-cancellation-request-pending") {
    return "이미 처리 중인 취소 요청이 있습니다. 잠시 후 다시 확인해 주세요.";
  }

  if (message === "billing-cancellation-request-not-found") {
    return "취소 요청 내역을 찾을 수 없습니다.";
  }

  if (message === "billing-cancellation-request-not-pending") {
    return "이미 처리가 시작되어 취소 요청을 되돌릴 수 없습니다.";
  }

  if (message === "billing-cancellation-withdrawal-no-successful-charge") {
    return "전액 청약철회 기준이 되는 성공 결제가 아직 없습니다.";
  }

  if (message === "billing-cancellation-withdrawal-outside-7-day-window") {
    return "전액 청약철회 가능 기간(결제 후 7일)이 지났습니다.";
  }

  if (message === "billing-cancellation-withdrawal-usage-history-exists") {
    return "메일 송수신 이력이 있어 전액 청약철회는 불가합니다. 일반 해지만 진행해 주세요.";
  }

  if (message === "billing-management-forbidden") {
    return "플랜 변경과 결제 관리는 각 도메인의 대표 관리자 계정에서만 가능합니다.";
  }

  if (message === "billing-cancellation-withdrawal-processing-failed") {
    return "청약철회 처리 중 오류가 발생했습니다. 잠시 후 다시 시도해 주세요.";
  }

  return message;
}

function pendingCancellationLabel(overview: MailBillingCancellationOverview | null) {
  if (!overview?.pendingRequest) {
    return "";
  }

  if (overview.pendingRequest.status === "processing") {
    return overview.pendingRequest.kind === "withdrawal_refund"
      ? "청약철회 처리 중"
      : "해지 처리 중";
  }

  return overview.pendingRequest.kind === "withdrawal_refund"
    ? "청약철회 요청됨"
    : "해지 요청됨";
}

function pricingCardClass(featured = false, active = false) {
  if (featured) {
    return `relative flex h-full flex-col rounded-[24px] border bg-white/96 p-6 shadow-[0_24px_54px_rgba(47,109,246,0.12)] ${
      active ? "border-[#8db4ff]" : "border-[#cfe0ff]"
    }`;
  }

  return `relative flex h-full flex-col rounded-[24px] border bg-white/96 p-6 shadow-[0_20px_44px_rgba(15,23,42,0.05)] ${
    active ? "border-[#9dc0ff]" : "border-[#e6edf8]"
  }`;
}

function primaryButtonClass(disabled = false) {
  return `om-btn-primary h-11 w-full rounded-[16px] px-5 text-[13px] ${
    disabled ? "cursor-not-allowed opacity-60" : "cursor-pointer"
  }`;
}

function secondaryButtonClass(disabled = false) {
  return `om-btn-secondary h-11 w-full rounded-[16px] px-5 text-[13px] ${
    disabled ? "cursor-not-allowed opacity-60" : "cursor-pointer"
  }`;
}

function dangerButtonClass(disabled = false) {
  return `inline-flex h-11 w-full items-center justify-center rounded-[16px] px-5 text-[13px] font-semibold transition-all duration-200 ${
    disabled
      ? "cursor-not-allowed border border-[#f0c5c8] bg-[#fff2f2] text-[#c7898d] opacity-70"
      : "cursor-pointer border border-[#dc3f45] bg-[#e5484d] text-white hover:bg-[#d83b40]"
  }`;
}

function PricingCheckBullet() {
  return (
    <span className="mt-0.5 flex h-5 w-5 shrink-0 items-center justify-center rounded-full bg-[#2f6df6] text-[12px] font-bold text-white">
      ✓
    </span>
  );
}

export function TossBillingModule({
  billingOverview,
  cancellationOverview,
  billingSeatCount,
  canManageBilling,
  currentTab,
  estimatedMonthlyCost,
  historyPage,
  historyState,
  isComplimentaryGrowthPlan,
  managedMembers,
  representativeMailbox,
}: TossBillingModuleProps) {
  const router = useRouter();
  const searchParams = useSearchParams();
  const [tabNavigationPending, startTabNavigationTransition] = useTransition();
  const [busyAction, setBusyAction] = useState<
    null | "cancel" | "register" | "revoke" | "start" | "withdraw"
  >(null);
  const [cardDragging, setCardDragging] = useState(false);
  const [cardRotation, setCardRotation] = useState({
    x: 0,
    y: 0,
    z: 0,
  });
  const [detailsOpen, setDetailsOpen] = useState(false);
  const [paymentModalOpen, setPaymentModalOpen] = useState(false);
  const [notice, setNotice] = useState("");
  const [billingUiStateOverride, setBillingUiStateOverride] =
    useState<BillingUiStateOverride | null>(null);
  const cardDragStateRef = useRef<{
    baseX: number;
    baseY: number;
    baseZ: number;
    pointerId: number;
    startX: number;
    startY: number;
  } | null>(null);

  const sourceProfile = billingOverview?.profile;
  const profile = sourceProfile
    ? {
        ...sourceProfile,
        billingKey:
          billingUiStateOverride?.billingProfileStatus === "removed"
            ? null
            : sourceProfile.billingKey,
        status: billingUiStateOverride?.billingProfileStatus ?? sourceProfile.status,
      }
    : null;
  const subscription = billingOverview?.subscription;
  const initialPaymentComplete =
    billingUiStateOverride?.initialPaymentComplete ??
    subscription?.initialPaymentComplete ??
    false;
  const subscriptionStatus =
    billingUiStateOverride?.subscriptionStatus ??
    (subscription?.status === "active" && !initialPaymentComplete
      ? "pending"
      : subscription?.status ?? null);
  const nextChargeAt =
    billingUiStateOverride?.nextChargeAt ?? subscription?.nextChargeAt ?? null;
  const billingRegistrationReturned =
    searchParams.get("success") === "billing-registration-returned";
  const billingProfileIsActive =
    profile?.status === "active" && Boolean(profile.billingKey);
  const billingProfileIsPending = profile?.status === "pending";
  const hasPaymentProfile = billingProfileIsActive || billingProfileIsPending;
  const growthPlanActive =
    isComplimentaryGrowthPlan ||
    (subscriptionStatus === "active" && initialPaymentComplete);
  const pendingCancellationRequest = cancellationOverview?.pendingRequest ?? null;
  const pendingLabel = pendingCancellationLabel(cancellationOverview);
  const actionLocked = busyAction !== null;
  const paymentMethodLabel = isComplimentaryGrowthPlan
    ? "등록 불필요"
    : paymentMethodSummary(
        billingOverview
          ? {
              ...billingOverview,
              profile,
            }
          : null,
      );
  const resolvedBillingSeatCount =
    billingOverview?.billingSeatCount ?? billingSeatCount;
  const billingSeatRows = [
    {
      id: "owner",
      email: representativeMailbox,
      label: "대표 메일",
      price: isComplimentaryGrowthPlan ? 0 : MAIL_GROWTH_PLAN_PRICE_PER_MEMBER,
      toneClass: "text-[#2f6df6]",
    },
    ...managedMembers.map((member) => ({
      id: `member-${member.id}`,
      email: member.email,
      label: member.displayName || "추가 멤버",
      price: isComplimentaryGrowthPlan ? 0 : MAIL_GROWTH_PLAN_PRICE_PER_MEMBER,
      toneClass: "text-[#5d6f8e]",
    })),
  ];
  const paymentChangeDisabled =
    isComplimentaryGrowthPlan || actionLocked || !canManageBilling;
  const growthSelectDisabled = !canManageBilling || actionLocked || growthPlanActive;
  const cancelDisabled =
    actionLocked || !canManageBilling || !cancellationOverview?.canCancelNow;
  const cancelAsWithdrawal = Boolean(cancellationOverview?.canWithdrawWithRefund);
  const cancellationButtonClass = cancelAsWithdrawal
    ? secondaryButtonClass(cancelDisabled)
    : dangerButtonClass(cancelDisabled);
  const revokePendingDisabled =
    actionLocked || !canManageBilling || pendingCancellationRequest?.status !== "pending";
  const paymentSummaryButtonLabel =
    isComplimentaryGrowthPlan
      ? "결제수단 등록 불필요"
      : busyAction === "register"
      ? "결제수단 등록 준비 중..."
      : hasPaymentProfile
        ? "결제수단 변경"
        : "결제수단 등록하기";
  const summaryHeadline = isComplimentaryGrowthPlan
    ? "관리자 무과금 성장 플랜"
    : growthPlanActive
      ? "자동결제가 준비된 결제카드"
      : "먼저 결제카드를 등록하세요";
  const summaryDescription = growthPlanActive
    ? isComplimentaryGrowthPlan
      ? "운영 계정 혜택으로 결제수단 등록과 멤버 과금 없이 성장 플랜 기능을 사용하고 있습니다."
      : `팀 인원 ${resolvedBillingSeatCount}명 기준으로 자동결제가 준비되어 있습니다. 카드를 드래그해서 확인하고, 다음 청구 전에 과금 기준과 결제수단 상태를 점검할 수 있습니다.`
    : "무료 플랜이어도 결제수단은 미리 등록해둘 수 있습니다. 카드를 드래그해 확인하고, 멤버가 추가되는 순간부터 성장 플랜 전환과 자동청구가 자연스럽게 이어지도록 준비해두세요.";
  const summaryPlanLabel = growthPlanActive ? "현재 플랜 · 성장" : "현재 플랜 · 무료";
  const summaryCardBrand = paymentBrandLabel(profile);
  const summaryCardNumber = paymentCardNumber(profile);
  const summaryCardHolder = paymentHolderName(representativeMailbox);
  const showPaymentCardPreview =
    !isComplimentaryGrowthPlan &&
    billingProfileIsActive &&
    profile?.payMethod === "CARD";
  const billingSummaryHeadline = isComplimentaryGrowthPlan
    ? "성장 플랜 이용 중"
    : billingProfileIsActive
    ? showPaymentCardPreview
      ? "등록된 결제카드"
      : "자동결제가 준비된 결제수단"
    : billingProfileIsPending
      ? "결제수단 등록을 마무리하세요"
      : "먼저 결제수단을 등록하세요";
  const billingSummaryDescription = isComplimentaryGrowthPlan
    ? "관리자 계정 혜택이 적용되어 결제수단과 자동 청구 없이 성장 플랜의 모든 기능을 사용할 수 있습니다."
    : billingProfileIsActive
    ? `팀 인원 ${resolvedBillingSeatCount}명 기준으로 자동결제가 준비되어 있습니다. 결제수단 상태와 다음 청구일을 여기서 바로 확인할 수 있습니다.`
    : billingProfileIsPending
      ? "결제수단 등록이 진행 중입니다. 인증이 완료되면 결제수단 정보와 자동결제 상태가 여기에 표시됩니다."
      : "무료 플랜이어도 결제수단은 미리 등록해둘 수 있습니다. 등록이 완료되면 카드 정보와 자동결제 상태를 여기서 바로 확인할 수 있습니다.";
  void summaryHeadline;
  void summaryDescription;
  const profileStatusText = isComplimentaryGrowthPlan
    ? "운영 혜택"
    : profileStatusLabel(profile?.status ?? null);
  const subscriptionStatusText = isComplimentaryGrowthPlan
    ? "관리자 무과금"
    : subscriptionStatusLabel(subscriptionStatus);
  const displayedNextChargeAt = isComplimentaryGrowthPlan ? null : nextChargeAt;
  const cardGlareStyle = {
    background: `radial-gradient(circle at ${34 + cardRotation.y * 0.45}% ${22 - cardRotation.x * 0.5}%, rgba(255,255,255,0.42), rgba(255,255,255,0.16) 16%, rgba(255,255,255,0) 42%)`,
    opacity: cardDragging ? 0.96 : 0.84,
  };
  const cardSheenStyle = {
    background: `linear-gradient(${118 + cardRotation.y * 0.22}deg, rgba(255,255,255,0) 18%, rgba(255,255,255,0.08) 34%, rgba(255,255,255,0.24) 48%, rgba(255,255,255,0.08) 58%, rgba(255,255,255,0) 74%)`,
    opacity: cardDragging ? 0.92 : 0.76,
  };
  const toastNotice: BottomToastNotice | null = notice
    ? {
        tone: /실패|오류|불가|필수|중복|금지|취소됐|찾을 수 없/.test(notice) ? "error" : "success",
        message: notice,
      }
    : null;
  const tabButtonClass = (active: boolean) =>
    `inline-flex h-9 items-center justify-center rounded-[10px] border px-3 text-[13px] font-semibold transition-colors ${
      active
        ? "border-[#bfd4ff] bg-[#eef4ff] text-[#2f6df6]"
        : "border-[#e2e8f3] bg-white text-[#6a7b97] hover:border-[#d4ddeb] hover:text-[#2d3d5c]"
    }`;

  useEffect(() => {
    if (!notice) {
      return;
    }

    const timer = window.setTimeout(() => {
      setNotice("");
    }, 4200);

    return () => window.clearTimeout(timer);
  }, [notice]);

  useEffect(() => {
    if (!billingRegistrationReturned) {
      return;
    }

    if (billingProfileIsActive) {
      startTabNavigationTransition(() => {
        router.replace("/mail?panel=setup&section=billing", { scroll: false });
      });
      return;
    }

    let refreshCount = 0;
    let timer: number | undefined;

    const refreshBillingStatus = () => {
      refreshCount += 1;
      startTabNavigationTransition(() => {
        router.refresh();
      });

      if (refreshCount < 12) {
        timer = window.setTimeout(refreshBillingStatus, 1000);
      }
    };

    refreshBillingStatus();

    return () => {
      if (timer !== undefined) {
        window.clearTimeout(timer);
      }
    };
  }, [billingProfileIsActive, billingRegistrationReturned, router, startTabNavigationTransition]);

  function refreshBillingOverview() {
    startTabNavigationTransition(() => {
      router.refresh();
    });
  }

  function navigateBillingTab(tab: MailBillingTab) {
    const href = buildMailBillingSetupHref({
      tab,
      from: historyState.from,
      page: historyState.page,
      rangePreset: historyState.rangePreset,
      to: historyState.to,
    });

    startTabNavigationTransition(() => {
      router.push(href, { scroll: false });
    });
  }

  function openPaymentModal() {
    setPaymentModalOpen(true);
  }

  function handleCardPointerDown(event: ReactPointerEvent<HTMLDivElement>) {
    event.preventDefault();
    event.currentTarget.setPointerCapture(event.pointerId);
    cardDragStateRef.current = {
      pointerId: event.pointerId,
      startX: event.clientX,
      startY: event.clientY,
      baseX: cardRotation.x,
      baseY: cardRotation.y,
      baseZ: cardRotation.z,
    };
    setCardDragging(true);
  }

  function handleCardPointerMove(event: ReactPointerEvent<HTMLDivElement>) {
    const dragState = cardDragStateRef.current;

    if (!dragState || dragState.pointerId !== event.pointerId) {
      return;
    }

    const deltaX = event.clientX - dragState.startX;

    setCardRotation({
      x: 0,
      y: dragState.baseY + deltaX * 0.6,
      z: 0,
    });
  }

  function handleCardPointerEnd(event: ReactPointerEvent<HTMLDivElement>) {
    if (cardDragStateRef.current?.pointerId !== event.pointerId) {
      return;
    }

    cardDragStateRef.current = null;
    setCardDragging(false);
    event.currentTarget.releasePointerCapture(event.pointerId);
  }

  async function handleGrowthPlanSelect() {
    if (growthSelectDisabled) {
      return;
    }

    if (billingProfileIsActive) {
      await handleSubscriptionActivate();
      return;
    }

    await handleRegister();
  }

  async function handleRegister() {
    setBusyAction("register");

    try {
      const response = await fetch("/api/payments/toss-pay/billing/register", {
        method: "POST",
      });
      const payload = (await response.json()) as BillingRegisterResponse | ApiErrorResponse;

      if (!response.ok || !("ok" in payload) || payload.ok !== true) {
        throw new Error(
          normalizeApiErrorMessage(
            payload as ApiErrorResponse,
            "결제수단 등록 요청에 실패했습니다.",
          ),
        );
      }

      window.location.href = payload.registration.checkoutUri;
      return;
    } catch (error) {
      setNotice(
        error instanceof Error ? error.message : "결제수단 등록 요청에 실패했습니다.",
      );
    } finally {
      setBusyAction(null);
    }
  }

  async function handleSubscriptionActivate() {
    setBusyAction("start");
    setNotice("성장 플랜 결제를 진행하고 있습니다.");

    try {
      const response = await fetch("/api/payments/toss-pay/subscription", {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
        },
        body: JSON.stringify({ action: "activate" }),
      });
      const payload = (await response.json()) as
        | BillingSubscriptionActionResponse
        | ApiErrorResponse;

      if (!response.ok || !("ok" in payload) || payload.ok !== true) {
        throw new Error(
          normalizeApiErrorMessage(
            payload as ApiErrorResponse,
            "성장 플랜 시작 처리에 실패했습니다.",
          ),
        );
      }

      setNotice(
        `성장 플랜 결제가 완료되었습니다. ${formatCurrency(payload.subscription.chargedAmount ?? estimatedMonthlyCost)}이 결제되었고, 다음 청구일은 ${formatDateLabel(payload.subscription.nextChargeAt)} 입니다.`,
      );
      setBillingUiStateOverride({
        initialPaymentComplete: payload.subscription.initialPaymentComplete ?? true,
        nextChargeAt: payload.subscription.nextChargeAt,
        subscriptionStatus: payload.subscription.status,
      });
      refreshBillingOverview();
    } catch (error) {
      setNotice(
        error instanceof Error ? error.message : "성장 플랜 시작 처리에 실패했습니다.",
      );
    } finally {
      setBusyAction(null);
    }
  }

  async function handlePendingCancellationRevoke() {
    if (revokePendingDisabled || !pendingCancellationRequest) {
      return;
    }

    const confirmed = window.confirm(
      pendingCancellationRequest.kind === "withdrawal_refund"
        ? "접수된 청약철회 요청을 취소할까요?\n\n취소 큐에 들어가기 전이라면 성장 플랜과 자동결제를 바로 유지할 수 있습니다."
        : "접수된 해지 요청을 취소할까요?\n\n자동결제와 현재 구독 상태를 그대로 유지합니다.",
    );

    if (!confirmed) {
      return;
    }

    setBusyAction("revoke");
    setNotice("취소 요청을 되돌리고 있습니다.");

    try {
      const response = await fetch("/api/payments/toss-pay/cancellation/request", {
        method: "DELETE",
      });
      const payload = (await response.json()) as
        | BillingCancellationActionResponse
        | ApiErrorResponse;

      if (!response.ok || !("ok" in payload) || payload.ok !== true) {
        throw new Error(
          normalizeApiErrorMessage(
            payload as ApiErrorResponse,
            "취소 요청 되돌리기에 실패했습니다.",
          ),
        );
      }

      setNotice(payload.message);
      setBillingUiStateOverride({
        subscriptionStatus: payload.cancellation.subscriptionStatus,
      });
      refreshBillingOverview();
    } catch (error) {
      setNotice(
        error instanceof Error
          ? error.message
          : "취소 요청 되돌리기에 실패했습니다.",
      );
    } finally {
      setBusyAction(null);
    }
  }

  async function handleCancellationRequest(
    kind: MailBillingCancellationRequestKind,
  ) {
    const confirmed = window.confirm(
      kind === "withdrawal_refund"
        ? "7일 이내 전액 청약철회를 진행할까요?\n\n결제가 바로 환불되고 성장 플랜이 즉시 철회됩니다. 추가 멤버 계정과 메시지 데이터, 업로드 파일도 함께 정리됩니다."
        : "정기결제를 해지할까요?\n\n환불 없이 다음 자동 청구부터 중단됩니다.",
    );

    if (!confirmed) {
      return;
    }

    setBusyAction(kind === "withdrawal_refund" ? "withdraw" : "cancel");
    setNotice(
      kind === "withdrawal_refund"
        ? "전액 청약철회를 처리하고 있습니다."
        : "정기결제 해지를 처리하고 있습니다.",
    );

    try {
      const response = await fetch(
        "/api/payments/toss-pay/cancellation/request",
        {
          method: "POST",
          headers: {
            "Content-Type": "application/json",
          },
          body: JSON.stringify({ kind }),
        },
      );
      const payload = (await response.json()) as
        | BillingCancellationActionResponse
        | ApiErrorResponse;

      if (!response.ok || !("ok" in payload) || payload.ok !== true) {
        throw new Error(
          normalizeApiErrorMessage(
            payload as ApiErrorResponse,
            kind === "withdrawal_refund"
              ? "전액 청약철회 요청 처리에 실패했습니다."
              : "정기결제 해지 처리에 실패했습니다.",
          ),
        );
      }

      setNotice(payload.message);
      setPaymentModalOpen(false);
      setBillingUiStateOverride({
        billingProfileStatus: "removed",
        nextChargeAt: null,
        subscriptionStatus: payload.cancellation.subscriptionStatus,
      });
      refreshBillingOverview();
    } catch (error) {
      setNotice(
        error instanceof Error
          ? error.message
          : kind === "withdrawal_refund"
            ? "전액 청약철회 요청 처리에 실패했습니다."
            : "정기결제 해지 처리에 실패했습니다.",
      );
    } finally {
      setBusyAction(null);
    }
  }

  return (
    <>
      <div className="space-y-4 px-3 py-3 sm:px-4 lg:px-5">
        <div className="flex flex-wrap items-center gap-2 border-b border-[#edf1f6] pb-3">
          <button
            type="button"
            aria-pressed={currentTab === "overview"}
            disabled={tabNavigationPending}
            onClick={() => navigateBillingTab("overview")}
            className={tabButtonClass(currentTab === "overview")}
          >
            구독 및 결제 설정
          </button>
          <button
            type="button"
            aria-pressed={currentTab === "history"}
            disabled={tabNavigationPending}
            onClick={() => navigateBillingTab("history")}
            className={tabButtonClass(currentTab === "history")}
          >
            결제내역
          </button>
        </div>

        {currentTab === "history" ? (
          <MailBillingHistoryPanel
            historyPage={historyPage}
            historyState={historyState}
          />
        ) : (
          <>
        <section className="om-setup-panel px-3 py-4 sm:px-4 lg:px-5">
          <div className="grid gap-7 xl:grid-cols-[minmax(320px,430px)_minmax(0,1fr)] xl:items-center">
            <div className="min-w-0">
              <p
                className={`mb-3 text-[12px] font-semibold uppercase tracking-[0.12em] text-[#8aa0c6] ${
                  showPaymentCardPreview ? "" : "hidden"
                }`}
              >
                드래그해서 카드 회전
              </p>
              {showPaymentCardPreview ? (
                <div className="[perspective:2200px]">
                <div
                  role="presentation"
                  onDoubleClick={() => setCardRotation({ x: 0, y: 0, z: 0 })}
                  onPointerCancel={handleCardPointerEnd}
                  onPointerDown={handleCardPointerDown}
                  onPointerMove={handleCardPointerMove}
                  onPointerUp={handleCardPointerEnd}
                  className={`relative mx-auto aspect-[1.62/1] w-full max-w-[410px] touch-none select-none [transform-style:preserve-3d] ${
                    cardDragging ? "cursor-grabbing" : "cursor-grab"
                  }`}
                  style={{
                    transform: `rotateX(${cardRotation.x}deg) rotateY(${cardRotation.y}deg) rotateZ(${cardRotation.z}deg)`,
                    transition: cardDragging ? "none" : "transform 260ms ease-out",
                  }}
                >
                  <div
                    className="absolute inset-0 overflow-hidden rounded-[10px] border border-white/14 shadow-[0_38px_90px_rgba(18,34,68,0.28)]"
                    style={{
                      backfaceVisibility: "hidden",
                      background:
                        "linear-gradient(140deg, rgba(7,18,39,1) 0%, rgba(16,40,89,1) 28%, rgba(40,96,197,1) 58%, rgba(116,180,255,1) 100%)",
                    }}
                  >
                    <div className="pointer-events-none absolute inset-0 bg-[linear-gradient(135deg,rgba(255,255,255,0.12),transparent_32%,rgba(255,255,255,0.04)_56%,rgba(152,209,255,0.16)_100%)]" />
                    <div className="pointer-events-none absolute inset-0 opacity-45 [background-image:linear-gradient(rgba(255,255,255,0.06)_1px,transparent_1px),linear-gradient(90deg,rgba(255,255,255,0.05)_1px,transparent_1px)] [background-size:28px_28px]" />
                    <div className="pointer-events-none absolute inset-0 mix-blend-screen" style={cardSheenStyle} />
                    <div className="pointer-events-none absolute inset-0 mix-blend-screen" style={cardGlareStyle} />
                    <div className="pointer-events-none absolute inset-[1px] rounded-[9px] border border-white/8" />
                    <div className="pointer-events-none absolute left-6 top-5 h-20 w-20 rounded-full bg-white/10 blur-3xl" />
                    <div className="pointer-events-none absolute -bottom-10 right-0 h-32 w-32 rounded-full bg-[#88d0ff]/24 blur-3xl" />
                    <div className="relative flex h-full flex-col justify-between p-6 text-white">
                      <div className="flex items-start justify-between gap-4">
                        <div className="space-y-3">
                          <p className="text-[11px] font-semibold uppercase tracking-[0.18em] text-white/78">
                            Officialmail Signature
                          </p>
                          <span className="om-badge om-badge-sm om-badge-glass h-7 px-2.5 text-[10px] uppercase tracking-[0.16em]">
                            {summaryPlanLabel}
                          </span>
                        </div>
                        <div className="flex flex-col items-end gap-3">
                          <p className="text-[11px] font-semibold uppercase tracking-[0.18em] text-white/68">
                            {summaryCardBrand}
                          </p>
                          <div className="relative h-8 w-12">
                            <span className="absolute left-0 top-0 h-8 w-8 rounded-full bg-white/82 mix-blend-screen" />
                            <span className="absolute right-0 top-0 h-8 w-8 rounded-full bg-[#ffb86a]/92 mix-blend-screen" />
                          </div>
                        </div>
                      </div>

                      <div className="space-y-5">
                        <div className="flex items-center justify-between gap-4">
                          <div className="relative h-12 w-[72px] rounded-[10px] border border-white/18 bg-[linear-gradient(145deg,rgba(255,255,255,0.3),rgba(255,255,255,0.08))] shadow-[inset_0_1px_0_rgba(255,255,255,0.24)]">
                            <div className="absolute inset-y-[8px] left-[24px] w-px bg-[#7d8aa7]/55" />
                            <div className="absolute inset-y-[8px] left-[44px] w-px bg-[#7d8aa7]/55" />
                            <div className="absolute left-[8px] right-[8px] top-[15px] h-px bg-[#7d8aa7]/45" />
                            <div className="absolute left-[8px] right-[8px] top-[27px] h-px bg-[#7d8aa7]/45" />
                          </div>
                          <div className="flex items-center gap-3">
                            <svg
                              viewBox="0 0 24 24"
                              fill="none"
                              className="h-6 w-6 text-white/72"
                              aria-hidden="true"
                            >
                              <path
                                d="M7.5 7.5c2.2 1 3.7 2.8 4.6 5.2M10.6 5.2c3.1 1.2 5.2 3.8 6.3 7.2M13.8 3c3.7 1.4 6.3 4.6 7.7 8.6"
                                stroke="currentColor"
                                strokeWidth="1.5"
                                strokeLinecap="round"
                              />
                            </svg>
                            <div className="relative h-11 w-11 overflow-hidden rounded-[10px] border border-white/14 bg-[linear-gradient(145deg,rgba(255,255,255,0.22),rgba(255,255,255,0.08))] shadow-[inset_0_1px_0_rgba(255,255,255,0.22)]">
                              <div className="absolute inset-[5px] rounded-[8px] bg-[conic-gradient(from_180deg_at_50%_50%,rgba(255,255,255,0.22),rgba(126,244,255,0.7),rgba(255,184,106,0.7),rgba(168,119,255,0.55),rgba(255,255,255,0.22))]" />
                            </div>
                          </div>
                        </div>

                        <div className="space-y-5">
                          <p
                            className="text-[14px] font-semibold tracking-[0.34em] text-white/96"
                            style={{ textShadow: "0 2px 16px rgba(255,255,255,0.18)" }}
                          >
                            {summaryCardNumber}
                          </p>
                          <div className="flex items-end justify-between gap-4">
                            <div className="grid gap-1.5">
                              <p className="text-[10px] font-semibold uppercase tracking-[0.14em] text-white/56">
                                Card Holder
                              </p>
                              <p className="text-[14px] font-semibold tracking-[0.08em] text-white/92">
                                {summaryCardHolder}
                              </p>
                            </div>
                            <div className="grid gap-1.5 text-right">
                              <p className="text-[10px] font-semibold uppercase tracking-[0.14em] text-white/56">
                                Valid Thru
                              </p>
                              <p className="text-[13px] font-semibold tracking-[0.08em] text-white/92">
                                12 / 29
                              </p>
                            </div>
                          </div>
                        </div>
                      </div>
                    </div>
                  </div>

                  <div
                    className="absolute inset-0 overflow-hidden rounded-[10px] border border-white/12 shadow-[0_38px_90px_rgba(18,34,68,0.22)]"
                    style={{
                      backfaceVisibility: "hidden",
                      transform: "rotateY(180deg)",
                      background:
                        "linear-gradient(145deg, rgba(8,18,37,1) 0%, rgba(20,35,71,1) 40%, rgba(29,83,188,1) 100%)",
                    }}
                  >
                    <div className="pointer-events-none absolute inset-0 bg-[linear-gradient(135deg,rgba(255,255,255,0.08),transparent_30%,rgba(110,172,255,0.14)_100%)]" />
                    <div className="pointer-events-none absolute inset-0 mix-blend-screen" style={cardSheenStyle} />
                    <div className="pointer-events-none absolute inset-[1px] rounded-[9px] border border-white/8" />
                    <div className="relative flex h-full flex-col px-0 py-5 text-white">
                      <div className="h-12 bg-[linear-gradient(180deg,rgba(7,13,24,0.98),rgba(20,26,43,0.96))] shadow-[inset_0_1px_0_rgba(255,255,255,0.06)]" />
                      <div className="flex flex-1 flex-col px-6">
                        <div className="mt-5 rounded-[10px] bg-[linear-gradient(180deg,rgba(255,255,255,0.5),rgba(255,255,255,0.14))] p-[1px]">
                          <div className="rounded-[9px] bg-white/92 px-4 py-3 text-right text-[#14233f] shadow-[inset_0_1px_0_rgba(255,255,255,0.4)]">
                            <p className="text-[10px] font-semibold uppercase tracking-[0.16em] text-[#6b7b97]">
                              Secure Code
                            </p>
                            <p className="mt-2 text-[18px] font-semibold tracking-[0.24em]">***</p>
                          </div>
                        </div>

                        <div className="mt-4 flex items-center justify-between gap-4">
                          <div>
                            <p className="text-[10px] font-semibold uppercase tracking-[0.16em] text-white/54">
                              Auto Billing
                            </p>
                            <p className="mt-2 text-[14px] font-semibold text-white/88">
                              {subscriptionStatusText}
                            </p>
                          </div>
                          <span className="om-badge om-badge-sm om-badge-glass px-3 uppercase tracking-[0.08em]">
                            {profileStatusText}
                          </span>
                        </div>

                        <div className="mt-auto flex items-end justify-between gap-4 border-t border-white/10 pt-4">
                          <p className="max-w-[180px] text-[12px] leading-6 text-white/72">
                            {paymentMethodLabel}
                          </p>
                          <p className="text-right text-[11px] font-semibold uppercase tracking-[0.18em] text-white/60">
                            Officialmail
                          </p>
                        </div>
                      </div>
                    </div>
                  </div>
                </div>
                </div>
              ) : (
                <div className="mx-auto flex w-full max-w-[410px] flex-col items-center justify-center gap-4 rounded-[20px] border border-dashed border-[#d8e3f8] bg-[linear-gradient(180deg,#fbfdff,#f7faff)] px-8 py-10 text-center">
                  <div className="flex h-14 w-14 items-center justify-center rounded-[16px] bg-[#f2f6fd] text-[#7a8ba7]">
                    <svg
                      viewBox="0 0 24 24"
                      fill="none"
                      stroke="currentColor"
                      strokeWidth="1.8"
                      strokeLinecap="round"
                      strokeLinejoin="round"
                      className="h-7 w-7"
                      aria-hidden="true"
                    >
                      <rect x="3.5" y="5.5" width="17" height="13" rx="2.5" />
                      <path d="M3.5 10.2h17" />
                      <path d="M7.5 15.2h3.2" />
                    </svg>
                  </div>
                  <div className="space-y-2">
                    <p className="text-[17px] font-semibold tracking-[-0.03em] text-[#16233c]">
                      {isComplimentaryGrowthPlan
                        ? "결제수단 등록 없이 이용 중"
                        : "등록된 결제카드가 없습니다"}
                    </p>
                    <p className="text-[13px] leading-6 text-[#70819d]">
                      {isComplimentaryGrowthPlan
                        ? "운영 계정 혜택이 적용되어 성장 플랜 기능을 바로 사용할 수 있습니다."
                        : "결제수단을 등록하면 카드 정보와 자동결제 상태가 여기 표시됩니다."}
                    </p>
                  </div>
                </div>
              )}
              <div className="mx-auto mt-4 w-full max-w-[410px] space-y-2">
                {!isComplimentaryGrowthPlan ? (
                  <button
                    type="button"
                    onClick={hasPaymentProfile ? openPaymentModal : handleRegister}
                    disabled={paymentChangeDisabled}
                    className={secondaryButtonClass(paymentChangeDisabled)}
                  >
                    {paymentSummaryButtonLabel}
                  </button>
                ) : null}
                {showPaymentCardPreview ? (
                  <p className="text-center text-[12px] leading-6 text-[#7f90ab]">
                    카드 더블클릭 시 기본 각도로 돌아옵니다.
                  </p>
                ) : null}
              </div>
            </div>

            <div className="min-w-0">
              <div className="flex flex-col gap-6">
                <div>
                  <div className="flex flex-wrap items-center gap-2">
                    <span className="om-badge om-badge-md om-badge-info">
                      {summaryPlanLabel}
                    </span>
                    <span className="om-badge om-badge-md om-badge-soft">
                      {profileStatusText}
                    </span>
                  </div>

                  <p className="mt-4 text-[13px] font-semibold uppercase tracking-[0.12em] text-[#7290c2]">
                    Billing Overview
                  </p>
                  <h3 className="mt-2 text-[30px] font-semibold leading-[1.12] tracking-[-0.05em] text-[#10203d] sm:text-[36px]">
                    {billingSummaryHeadline}
                  </h3>
                  <p className="mt-3 max-w-[760px] text-[14px] leading-7 text-[#617492] sm:text-[15px]">
                    {billingSummaryDescription}
                  </p>
                </div>

                <div className="grid gap-x-8 gap-y-5 sm:grid-cols-2">
                  <div className="border-b border-[#e7edf8] pb-4">
                    <p className="text-[12px] font-semibold uppercase tracking-[0.08em] text-[#8c9ab1]">
                      결제수단
                    </p>
                    <p className="mt-2 break-all text-[15px] font-semibold text-[#16233c]">
                      {paymentMethodLabel}
                    </p>
                  </div>
                  <div className="border-b border-[#e7edf8] pb-4">
                    <p className="text-[12px] font-semibold uppercase tracking-[0.08em] text-[#8c9ab1]">
                      자동결제 상태
                    </p>
                    <p className="mt-2 text-[15px] font-semibold text-[#16233c]">
                      {subscriptionStatusText}
                    </p>
                  </div>
                  <div className="border-b border-[#e7edf8] pb-4">
                    <p className="text-[12px] font-semibold uppercase tracking-[0.08em] text-[#8c9ab1]">
                      다음 청구일
                    </p>
                    <p className="mt-2 text-[15px] font-semibold text-[#16233c]">
                      {isComplimentaryGrowthPlan
                        ? "청구 없음"
                        : formatDateLabel(displayedNextChargeAt)}
                    </p>
                  </div>
                  <div className="border-b border-[#e7edf8] pb-4">
                    <p className="text-[12px] font-semibold uppercase tracking-[0.08em] text-[#8c9ab1]">
                      현재 예상 요금
                    </p>
                    <p className="mt-2 text-[28px] font-semibold tracking-[-0.05em] text-[#10203d]">
                      {formatCurrency(estimatedMonthlyCost)}
                    </p>
                    <p className="mt-1 text-[13px] leading-6 text-[#70819d]">
                      {isComplimentaryGrowthPlan
                        ? "운영 계정 혜택 적용"
                        : `팀 인원 ${resolvedBillingSeatCount}명 기준`}
                    </p>
                  </div>
                </div>

                <div className="hidden flex-col gap-3 sm:flex-row sm:items-center">
                  <button
                    type="button"
                    onClick={hasPaymentProfile ? openPaymentModal : handleRegister}
                    disabled={paymentChangeDisabled}
                    className={`hidden ${secondaryButtonClass(paymentChangeDisabled)} sm:w-auto sm:min-w-[200px]`}
                  >
                    {paymentSummaryButtonLabel}
                  </button>
                  <p
                    className={`hidden text-[12px] leading-6 text-[#7f90ab] ${
                      showPaymentCardPreview ? "" : "hidden"
                    }`}
                  >
                    카드 더블클릭 시 기본 각도로 돌아옵니다.
                  </p>
                </div>
              </div>
            </div>
          </div>
        </section>

        <div className="grid gap-5 xl:grid-cols-3">
          <article className={pricingCardClass(false, !growthPlanActive)}>
            <div className="flex items-start justify-between gap-3">
              <div>
                <p className="text-[11px] font-bold uppercase tracking-[0.1em] text-[#8c9ab1]">
                  {MAIL_FREE_PLAN_CARD.label}
                </p>
                <h3 className="mt-2 text-[26px] font-extrabold tracking-[-0.05em] text-[#061832]">
                  {MAIL_FREE_PLAN_CARD.title}
                </h3>
              </div>
              {!growthPlanActive ? (
                <span className="om-badge om-badge-md om-badge-soft">
                  현재 이용 중
                </span>
              ) : null}
            </div>
            <p className="mt-3 text-[14px] font-medium leading-6 text-[#6c7a93]">
              {MAIL_FREE_PLAN_CARD.description}
            </p>
            <div className="mt-8 min-h-[96px]">
              <div className="flex items-end gap-2">
                <span className="text-[42px] font-black leading-none tracking-[-0.08em] text-[#061832]">
                  {MAIL_FREE_PLAN_CARD.price}
                </span>
              </div>
              <p className="mt-3 text-[14px] font-medium text-[#98a4b9]">
                {MAIL_FREE_PLAN_CARD.note}
              </p>
            </div>
            <div className="my-6 h-px w-full bg-[#edf2fb]" />
            <ul className="flex flex-1 flex-col gap-3 text-[15px] leading-[1.55] text-[#465468]">
              {MAIL_FREE_PLAN_CARD.features.map((feature) => (
                <li key={feature} className="flex items-start gap-3">
                  <PricingCheckBullet />
                  <span>{feature}</span>
                </li>
              ))}
            </ul>
            <div className="mt-8">
              <button
                type="button"
                disabled
                className={secondaryButtonClass(true)}
              >
                {!growthPlanActive ? "현재 무료 사용 중" : "기본 제공 플랜"}
              </button>
            </div>
          </article>

          <article className={pricingCardClass(true, growthPlanActive)}>
            <div className="absolute left-1/2 top-0 -translate-x-1/2 -translate-y-1/2 rounded-[10px] bg-[linear-gradient(135deg,#ff8a1d,#ff6a00)] px-4 py-1.5 text-[11px] font-bold tracking-[-0.02em] text-white shadow-[0_12px_24px_rgba(255,122,24,0.22)]">
              가장 많이 선택
            </div>
            <div className="flex items-start justify-between gap-3">
              <div>
                <p className="text-[11px] font-bold uppercase tracking-[0.1em] text-[#2f6df6]">
                  {MAIL_GROWTH_PLAN_CARD.label}
                </p>
                <h3 className="mt-2 text-[26px] font-extrabold tracking-[-0.05em] text-[#061832]">
                  {MAIL_GROWTH_PLAN_CARD.title}
                </h3>
              </div>
              {growthPlanActive ? (
                <span className="om-badge om-badge-md om-badge-info">
                  현재 이용 중
                </span>
              ) : null}
            </div>
            {pendingLabel ? (
              <span className="mt-4 om-badge om-badge-md om-badge-info w-fit">
                {pendingLabel}
              </span>
            ) : null}
            <p className="mt-3 text-[14px] font-medium leading-6 text-[#6c7a93]">
              {MAIL_GROWTH_PLAN_CARD.description}
            </p>
            <div className="mt-8 min-h-[96px]">
              <div className="flex items-end gap-2">
                <span className="text-[48px] font-black leading-none tracking-[-0.08em] text-[#2f6df6]">
                  {formatCurrency(MAIL_GROWTH_PLAN_PRICE_PER_MEMBER)}
                </span>
                <span className="mb-1 text-[14px] font-bold text-[#98a4b9]">
                  {MAIL_GROWTH_PLAN_CARD.priceSuffix}
                </span>
              </div>
              <p className="mt-3 text-[14px] font-medium text-[#98a4b9]">
                {growthPlanActive
                  ? `팀 인원 ${resolvedBillingSeatCount}명 기준 ${formatCurrency(estimatedMonthlyCost)}`
                  : MAIL_GROWTH_PLAN_CARD.note}
              </p>
            </div>
            <div className="my-6 h-px w-full bg-[#edf2fb]" />
            <ul className="flex flex-1 flex-col gap-3 text-[15px] leading-[1.55] text-[#465468]">
              {MAIL_GROWTH_PLAN_CARD.features.map((feature) => (
                <li key={feature} className="flex items-start gap-3">
                  <PricingCheckBullet />
                  <span>{feature}</span>
                </li>
              ))}
            </ul>
            <div className="mt-8 space-y-3">
              {growthPlanActive ? (
                isComplimentaryGrowthPlan ? (
                  <div className="rounded-[16px] border border-[#cfe0ff] bg-[#f5f8ff] px-4 py-3 text-center text-[13px] font-semibold text-[#2f6df6]">
                    운영 계정 혜택 적용됨 · 결제수단 등록 및 자동 청구 없음
                  </div>
                ) : (
                  <>
                  <button
                    type="button"
                    onClick={openPaymentModal}
                    disabled={paymentChangeDisabled}
                    className={primaryButtonClass(paymentChangeDisabled)}
                  >
                    {busyAction === "register"
                      ? "결제수단 변경 준비 중..."
                      : billingProfileIsPending
                        ? "토스 인증 대기 중"
                        : "결제수단 변경"}
                  </button>
                  <button
                    type="button"
                    onClick={() =>
                      handleCancellationRequest(
                        cancelAsWithdrawal ? "withdrawal_refund" : "cancel_only",
                      )
                    }
                    disabled={cancelDisabled}
                    className={cancellationButtonClass}
                  >
                    {busyAction === "withdraw"
                      ? "청약철회 처리 중..."
                      : busyAction === "cancel"
                        ? "해지 처리 중..."
                      : cancelAsWithdrawal
                          ? "청약철회하기"
                          : "해지하기"}
                  </button>
                  </>
                )
              ) : (
                pendingCancellationRequest ? (
                  <button
                    type="button"
                    onClick={handlePendingCancellationRevoke}
                    disabled={revokePendingDisabled}
                    className={primaryButtonClass(revokePendingDisabled)}
                  >
                    {busyAction === "revoke"
                      ? "취소 요청 되돌리는 중..."
                      : pendingCancellationRequest.status === "processing"
                        ? "취소 처리 중..."
                        : "취소 요청 취소"}
                  </button>
                ) : (
                  <button
                    type="button"
                    onClick={handleGrowthPlanSelect}
                    disabled={growthSelectDisabled}
                    className={primaryButtonClass(growthSelectDisabled)}
                  >
                    {busyAction === "register"
                      ? "결제수단 등록 준비 중..."
                      : busyAction === "start"
                        ? "성장 플랜 시작 중..."
                        : billingProfileIsPending
                          ? "변경하기"
                          : billingProfileIsActive
                            ? "성장 플랜 시작하기"
                            : "성장 플랜 선택하기"}
                  </button>
                )
              )}
              <button
                type="button"
                onClick={() => setDetailsOpen(true)}
                className={secondaryButtonClass(false)}
              >
                자세히보기
              </button>
            </div>
          </article>

          <article className={pricingCardClass()}>
            <div className="flex items-start justify-between gap-3">
              <div>
                <p className="text-[11px] font-bold uppercase tracking-[0.1em] text-[#8c9ab1]">
                  {MAIL_TEAM_PLAN_CARD.label}
                </p>
                <h3 className="mt-2 text-[26px] font-extrabold tracking-[-0.05em] text-[#061832]">
                  {MAIL_TEAM_PLAN_CARD.title}
                </h3>
              </div>
              <span className="om-badge om-badge-md om-badge-soft">
                준비 중
              </span>
            </div>
            <p className="mt-3 text-[14px] font-medium leading-6 text-[#6c7a93]">
              {MAIL_TEAM_PLAN_CARD.description}
            </p>
            <div className="mt-8 min-h-[96px]">
              <div className="flex items-end gap-2">
                <span className="text-[42px] font-black leading-none tracking-[-0.08em] text-[#061832]">
                  {MAIL_TEAM_PLAN_CARD.price}
                </span>
              </div>
              <p className="mt-3 text-[14px] font-medium text-[#98a4b9]">
                {MAIL_TEAM_PLAN_CARD.note}
              </p>
            </div>
            <div className="my-6 h-px w-full bg-[#edf2fb]" />
            <ul className="flex flex-1 flex-col gap-3 text-[15px] leading-[1.55] text-[#465468]">
              {MAIL_TEAM_PLAN_CARD.features.map((feature) => (
                <li key={feature} className="flex items-start gap-3">
                  <PricingCheckBullet />
                  <span>{feature}</span>
                </li>
              ))}
            </ul>
          </article>
        </div>

        {!canManageBilling ? (
          <p className="text-[13px] leading-6 text-[#70819d]">
            플랜 변경과 결제 등록은 각 도메인의 대표 관리자 계정에서만 진행할 수
            있습니다.
          </p>
        ) : null}
          </>
        )}
      </div>

      {detailsOpen ? (
        <div
          className="fixed inset-0 z-[140] flex items-center justify-center bg-[rgba(12,18,31,0.42)] px-4"
          onClick={() => setDetailsOpen(false)}
        >
          <div
            className="w-full max-w-[920px] rounded-[18px] border border-[#dfe6f2] bg-white px-5 py-6 shadow-[0_24px_72px_rgba(15,23,42,0.18)] sm:px-7 lg:px-8"
            onClick={(event) => event.stopPropagation()}
          >
            <div className="flex items-start justify-between gap-4">
              <div className="min-w-0">
                <p className="text-[24px] font-semibold tracking-[-0.04em] text-[#16233c]">
                  메일함별 과금 기준
                </p>
                <p className="mt-2 text-[14px] leading-7 text-[#6a7b98]">
                  {isComplimentaryGrowthPlan
                    ? "운영 계정 혜택으로 대표 메일과 추가 멤버 메일함을 모두 무과금으로 운영합니다."
                    : `성장 플랜에서는 대표 메일과 추가 멤버를 포함한 전체 팀 인원 1명당 ${formatCurrency(
                        MAIL_GROWTH_PLAN_PRICE_PER_MEMBER,
                      )}이 적용됩니다. 멤버를 추가하면 다음 자동결제 시점에 전체 팀 인원 기준으로 한 번에 청구됩니다.`}
                </p>
              </div>
              <CloseIconButton
                ariaLabel="멤버별 과금 기준 닫기"
                onClick={() => setDetailsOpen(false)}
              />
            </div>

            <div className="mt-6 grid gap-4 lg:grid-cols-[minmax(0,1fr)_228px]">
              <div className="overflow-x-auto border border-[#e7edf8]">
                <div className="min-w-[560px]">
                  <div className="grid grid-cols-[minmax(260px,1fr)_112px_100px] gap-3 border-b border-[#e7edf8] bg-[#fafcff] px-5 py-3 text-[11px] font-semibold uppercase tracking-[0.08em] text-[#7d8ca8]">
                    <span>메일함</span>
                    <span>구분</span>
                    <span className="text-right">월 요금</span>
                  </div>
                  {billingSeatRows.map((row) => (
                    <div
                      key={row.id}
                      className="grid grid-cols-[minmax(260px,1fr)_112px_100px] gap-3 border-b border-[#edf2fb] px-5 py-4 last:border-b-0"
                    >
                      <div className="min-w-0">
                        <p className="whitespace-nowrap text-[15px] font-semibold text-[#16233c]">
                          {row.email}
                        </p>
                      </div>
                      <div className="flex items-center">
                        <span className={`whitespace-nowrap text-[13px] font-medium ${row.toneClass}`}>
                          {row.label}
                        </span>
                      </div>
                      <div className="flex items-center justify-end text-right">
                        <span className="whitespace-nowrap text-[14px] font-semibold text-[#16233c]">
                          {formatCurrency(row.price)}
                        </span>
                      </div>
                    </div>
                  ))}
                </div>
              </div>

              <div className="border border-[#e7edf8] px-5 py-5">
                <div className="border-b border-[#edf2fb] pb-4">
                  <p className="text-[12px] font-semibold uppercase tracking-[0.08em] text-[#8c9ab1]">
                    현재 결제 기준
                  </p>
                  <p className="mt-2 text-[22px] font-semibold tracking-[-0.04em] text-[#16233c]">
                    팀 인원 {resolvedBillingSeatCount}명
                  </p>
                  <p className="mt-2 text-[13px] leading-6 text-[#70819d]">
                    {isComplimentaryGrowthPlan
                      ? "운영 계정 혜택이 적용되어 자동결제가 발생하지 않습니다."
                      : "성장 플랜에서는 대표 메일과 추가 멤버를 포함한 전체 팀 인원이 다음 자동결제 금액에 반영됩니다."}
                  </p>
                </div>
                <div className="pt-4">
                  <p className="text-[12px] font-semibold uppercase tracking-[0.08em] text-[#8c9ab1]">
                    현재 예상 월 요금
                  </p>
                  <p className="mt-2 text-[30px] font-semibold tracking-[-0.05em] text-[#10203d]">
                    {formatCurrency(estimatedMonthlyCost)}
                  </p>
                  <p className="mt-2 text-[13px] leading-6 text-[#70819d]">
                    익월 자동결제 시점 직전에 현재 팀 인원 수를 다시 계산해
                    한 번에 청구합니다.
                  </p>
                </div>
              </div>
            </div>
          </div>
        </div>
      ) : null}

      {paymentModalOpen ? (
        <div
          className="fixed inset-0 z-[150] flex items-center justify-center bg-[rgba(12,18,31,0.42)] px-4"
          onClick={() => setPaymentModalOpen(false)}
        >
          <div
            className="w-full max-w-[560px] rounded-[24px] border border-[#dfe8f7] bg-white p-6 shadow-[0_28px_80px_rgba(15,23,42,0.2)]"
            onClick={(event) => event.stopPropagation()}
          >
            <div className="flex items-start justify-between gap-4">
              <div className="min-w-0">
                <p className="text-[24px] font-semibold tracking-[-0.04em] text-[#16233c]">
                  등록된 결제수단
                </p>
                <p className="mt-2 text-[14px] leading-7 text-[#6a7b98]">
                  현재 등록된 카드나 토스머니를 확인하고 다시 등록할 수 있습니다.
                </p>
              </div>
              <CloseIconButton
                ariaLabel="결제수단 모달 닫기"
                onClick={() => setPaymentModalOpen(false)}
              />
            </div>

            <div className="mt-6 rounded-[20px] border border-[#edf2fb] bg-[#fbfcff] px-5 py-5">
              <div className="flex flex-wrap items-center justify-between gap-3">
                <div className="min-w-0">
                  <p className="text-[12px] font-semibold text-[#6f819f]">
                    현재 결제수단
                  </p>
                  <p className="mt-2 break-all text-[22px] font-semibold tracking-[-0.04em] text-[#16233c]">
                    {paymentMethodLabel}
                  </p>
                </div>
                <span className="om-badge om-badge-md om-badge-info">
                  {profileStatusText}
                </span>
              </div>

              <div className="mt-5 space-y-3 text-[14px] leading-6 text-[#465468]">
                <div className="flex items-start justify-between gap-4">
                  <span className="text-[#7c8baa]">플랜 상태</span>
                  <span className="text-right font-semibold text-[#16233c]">
                    {growthPlanActive ? "성장 플랜" : "무료 플랜"}
                  </span>
                </div>
                <div className="flex items-start justify-between gap-4">
                  <span className="text-[#7c8baa]">자동결제 상태</span>
                  <span className="text-right font-semibold text-[#16233c]">
                    {subscriptionStatusText}
                  </span>
                </div>
                <div className="flex items-start justify-between gap-4">
                  <span className="text-[#7c8baa]">다음 청구일</span>
                  <span className="text-right font-semibold text-[#16233c]">
                    {isComplimentaryGrowthPlan
                      ? "청구 없음"
                      : formatDateLabel(displayedNextChargeAt)}
                  </span>
                </div>
                <div className="flex items-start justify-between gap-4">
                  <span className="text-[#7c8baa]">팀 인원</span>
                  <span className="text-right font-semibold text-[#16233c]">
                    {resolvedBillingSeatCount}명
                  </span>
                </div>
                <div className="flex items-start justify-between gap-4">
                  <span className="text-[#7c8baa]">예상 월 요금</span>
                  <span className="text-right font-semibold text-[#16233c]">
                    {formatCurrency(estimatedMonthlyCost)}
                  </span>
                </div>
              </div>
            </div>

            {!isComplimentaryGrowthPlan ? (
              <div className="mt-5 flex flex-col gap-3">
                <button
                  type="button"
                  onClick={handleRegister}
                  disabled={paymentChangeDisabled}
                  className={primaryButtonClass(paymentChangeDisabled)}
                >
                  {busyAction === "register"
                    ? "결제수단 변경 준비 중..."
                    : hasPaymentProfile
                      ? "결제수단 변경"
                      : "결제수단 등록하기"}
                </button>
                <p className="text-[13px] leading-6 text-[#70819d]">
                  다시 등록하면 이후 자동결제는 새로 등록한 수단으로 갱신됩니다.
                </p>
              </div>
            ) : null}
          </div>
        </div>
      ) : null}

      {toastNotice ? (
        <BottomToast
          notice={toastNotice}
          onClose={() => setNotice("")}
        />
      ) : null}
    </>
  );
}
