import Link from "next/link";
import { notFound } from "next/navigation";
import { KavenixCancellationReviewActions } from "@/components/kavenix-cancellation-review-actions";
import { KavenixChargeDetailsDialog } from "@/components/kavenix-charge-details-dialog";
import { KavenixChargeRefundButton } from "@/components/kavenix-charge-refund-button";
import { KavenixDomainDnsPopover } from "@/components/kavenix-domain-dns-popover";
import {
  KavenixDomainRepairAllButton,
  KavenixDomainRepairButton,
} from "@/components/kavenix-domain-repair-button";
import { KavenixMemberCreateDialog } from "@/components/kavenix-member-create-dialog";
import { KavenixMailboxSyncButton } from "@/components/kavenix-mailbox-sync-button";
import { KavenixStatisticsDashboard } from "@/components/kavenix-statistics-dashboard";
import { KavenixMarketingPagination } from "@/components/kavenix-marketing-pagination";
import { KavenixMarketingProductFunnelDetailButton } from "@/components/kavenix-marketing-product-funnel-detail-button";
import { KavenixUserAuthActivityDialog } from "@/components/kavenix-user-auth-activity-dialog";
import { getMailEntryUrlForCurrentRequest, requireSessionUser } from "@/lib/auth";
import {
  getKavenixAdminDataset,
  getKavenixAdminMailboxById,
  isKavenixAdminEmail,
  normalizeKavenixChargeFilter,
  type KavenixAdminChargeFilter,
  type KavenixAdminChargeRefundState,
  type KavenixAdminChargeRow,
  type KavenixAdminDomainRow,
  type KavenixAdminMailboxRow,
  type KavenixAdminSummary,
  type KavenixAdminUserRow,
} from "@/lib/kavenix-admin";
import {
  getKavenixMarketingAnalytics,
  getKavenixMarketingVisitorCount,
  normalizeKavenixMarketingDrilldown,
  normalizeKavenixMarketingRangeDays,
  type KavenixMarketingAnalytics,
  type KavenixMarketingDrilldown,
  type KavenixMarketingDrilldownDimension,
  type KavenixMarketingRangeDays,
} from "@/lib/marketing-analytics";
import {
  getKavenixStatistics,
  normalizeKavenixStatisticsRange,
} from "@/lib/kavenix-statistics";
import { KavenixDomainCleanupButton } from "@/components/kavenix-domain-cleanup-button";
import { KavenixDomainOperationalBenefitToggle } from "@/components/kavenix-domain-operational-benefit-toggle";
import { KavenixDomainSendingServerSelect } from "@/components/kavenix-domain-sending-server-select";
import { KavenixPrimaryEmailChangeButton } from "@/components/kavenix-primary-email-change-button";
import { KavenixGoogleSearchConsoleDashboard } from "@/components/kavenix-google-search-console-dashboard";
import { KavenixBlogEditor } from "@/components/kavenix-blog-editor";
import { KavenixDomainAssistanceDashboard } from "@/components/kavenix-domain-assistance-dashboard";
import { KavenixDkimReminderDashboard } from "@/components/kavenix-dkim-reminder-dashboard";
import { KavenixPromotionCodeDashboard } from "@/components/kavenix-promotion-code-dashboard";
import { KavenixAppVersionDashboard } from "@/components/kavenix-app-version-dashboard";
import { KavenixSendingServerDashboard } from "@/components/kavenix-sending-server-dashboard";
import {
  getKavenixGoogleSearchConsoleAnalytics,
  getKavenixGoogleSearchConsoleBlogStatus,
} from "@/lib/google-search-console";
import { getMailAbsoluteUrl, getPublicSiteAbsoluteUrl } from "@/lib/mail-urls";
import {
  getKavenixMarketingBlogPostCount,
  getKavenixMarketingBlogPosts,
} from "@/lib/marketing-blog";
import {
  getKavenixDomainSetupAssistanceRequestCount,
  getKavenixDomainSetupAssistanceRequests,
} from "@/lib/domain-setup-assistance";
import {
  getKavenixDomainSetupPromotionCodeCount,
  getKavenixDomainSetupPromotionCodes,
} from "@/lib/domain-setup-promotions";
import {
  DEFAULT_DKIM_REMINDER_TEMPLATES,
  getKavenixDkimReminderRows,
} from "@/lib/dkim-reminders";
import {
  getMailAppOverviewByEmail,
  refreshMailboxIfStaleByEmail,
  type MailAppOverview,
  type MailMessageSummary,
} from "@/lib/official-mail";

export const metadata = {
  title: "Kavenix Admin | 오피셜메일",
  description: "오피셜메일 최고관리자 대시보드",
};

type AdminView =
  | "statistics"
  | "analytics"
  | "search"
  | "blog"
  | "users"
  | "domains"
  | "sending-servers"
  | "dkim-reminders"
  | "domain-assistance"
  | "promotion-codes"
  | "app-versions"
  | "mailboxes"
  | "charges";

const ADMIN_X_PADDING = "px-3 sm:px-4 lg:px-8";
const ADMIN_CELL_START = "pl-3 sm:pl-4 lg:pl-8";
const ADMIN_CELL_END = "pr-3 sm:pr-4 lg:pr-8";

type AdminNavItem = {
  count?: number;
  description: string;
  label: string;
  view: AdminView;
};

function MenuIcon({ className }: { className?: string }) {
  return (
    <svg
      viewBox="0 0 24 24"
      fill="none"
      stroke="currentColor"
      strokeWidth="1.8"
      strokeLinecap="round"
      strokeLinejoin="round"
      className={className}
      aria-hidden="true"
    >
      <path d="M4.5 7h15" />
      <path d="M4.5 12h15" />
      <path d="M4.5 17h15" />
    </svg>
  );
}

function ArrowLeftIcon({ className }: { className?: string }) {
  return (
    <svg
      viewBox="0 0 24 24"
      fill="none"
      stroke="currentColor"
      strokeWidth="1.8"
      strokeLinecap="round"
      strokeLinejoin="round"
      className={className}
      aria-hidden="true"
    >
      <path d="M15 5 8 12l7 7" />
    </svg>
  );
}

function AdminViewIcon({ className, view }: { className?: string; view: AdminView }) {
  if (view === "statistics") {
    return (
      <svg
        viewBox="0 0 24 24"
        fill="none"
        stroke="currentColor"
        strokeWidth="1.8"
        strokeLinecap="round"
        strokeLinejoin="round"
        className={className}
        aria-hidden="true"
      >
        <path d="M4 18.5h16" />
        <path d="M6.5 15.5v-4" />
        <path d="M11.9 15.5V6" />
        <path d="M17.5 15.5V9" />
        <path d="m5.8 8.2 4.6-3 4.1 2.1 4-3" />
      </svg>
    );
  }

  if (view === "analytics") {
    return (
      <svg
        viewBox="0 0 24 24"
        fill="none"
        stroke="currentColor"
        strokeWidth="1.8"
        strokeLinecap="round"
        strokeLinejoin="round"
        className={className}
        aria-hidden="true"
      >
        <path d="M4.5 19.5V5.5" />
        <path d="M4.5 19.5h15" />
        <path d="m7.4 15.5 3-3.2 2.8 1.8 4-5.2" />
        <path d="M15.8 8.9h1.4v1.4" />
      </svg>
    );
  }

  if (view === "search") {
    return (
      <svg
        viewBox="0 0 24 24"
        fill="none"
        stroke="currentColor"
        strokeWidth="1.8"
        strokeLinecap="round"
        strokeLinejoin="round"
        className={className}
        aria-hidden="true"
      >
        <circle cx="10.5" cy="10.5" r="5.8" />
        <path d="m15 15 4.5 4.5" />
        <path d="M8.2 10.5h4.6" />
      </svg>
    );
  }

  if (view === "blog") {
    return (
      <svg
        viewBox="0 0 24 24"
        fill="none"
        stroke="currentColor"
        strokeWidth="1.8"
        strokeLinecap="round"
        strokeLinejoin="round"
        className={className}
        aria-hidden="true"
      >
        <path d="M6.5 4.5h8.2l2.8 2.8v12.2H6.5z" />
        <path d="M14.5 4.5v3h3" />
        <path d="M9 11h6" />
        <path d="M9 14.5h6" />
      </svg>
    );
  }

  if (view === "domains") {
    return (
      <svg
        viewBox="0 0 24 24"
        fill="none"
        stroke="currentColor"
        strokeWidth="1.8"
        strokeLinecap="round"
        strokeLinejoin="round"
        className={className}
        aria-hidden="true"
      >
        <circle cx="12" cy="12" r="8.2" />
        <path d="M4.3 9.4h15.4" />
        <path d="M4.3 14.6h15.4" />
        <path d="M12 3.8c2 2.2 3.1 5 3.1 8.2s-1.1 6-3.1 8.2" />
        <path d="M12 3.8c-2 2.2-3.1 5-3.1 8.2s1.1 6 3.1 8.2" />
      </svg>
    );
  }

  if (view === "domain-assistance") {
    return (
      <svg
        viewBox="0 0 24 24"
        fill="none"
        stroke="currentColor"
        strokeWidth="1.8"
        strokeLinecap="round"
        strokeLinejoin="round"
        className={className}
        aria-hidden="true"
      >
        <path d="M4.5 6.5h15v11h-15z" />
        <path d="m5.5 7.5 6.5 5 6.5-5" />
        <path d="M17.2 15.4h3.3" />
        <path d="M18.85 13.75v3.3" />
      </svg>
    );
  }

  if (view === "dkim-reminders") {
    return (
      <svg
        viewBox="0 0 24 24"
        fill="none"
        stroke="currentColor"
        strokeWidth="1.8"
        strokeLinecap="round"
        strokeLinejoin="round"
        className={className}
        aria-hidden="true"
      >
        <path d="M12 3.8 19 6.5v5.2c0 4.3-2.8 7.2-7 8.5-4.2-1.3-7-4.2-7-8.5V6.5z" />
        <path d="M9 12.1 11.1 14l4-4.2" />
      </svg>
    );
  }

  if (view === "promotion-codes") {
    return (
      <svg
        viewBox="0 0 24 24"
        fill="none"
        stroke="currentColor"
        strokeWidth="1.8"
        strokeLinecap="round"
        strokeLinejoin="round"
        className={className}
        aria-hidden="true"
      >
        <path d="M4.5 7.2A2.2 2.2 0 0 1 6.7 5h10.6a2.2 2.2 0 0 1 2.2 2.2v2a2.8 2.8 0 0 0 0 5.6v2a2.2 2.2 0 0 1-2.2 2.2H6.7a2.2 2.2 0 0 1-2.2-2.2v-2a2.8 2.8 0 0 0 0-5.6z" />
        <path d="M12 8v8" />
        <path d="M9 12h6" />
      </svg>
    );
  }

  if (view === "charges") {
    return (
      <svg
        viewBox="0 0 24 24"
        fill="none"
        stroke="currentColor"
        strokeWidth="1.8"
        strokeLinecap="round"
        strokeLinejoin="round"
        className={className}
        aria-hidden="true"
      >
        <rect x="4" y="6" width="16" height="12" rx="2.6" />
        <path d="M4 10h16" />
        <path d="M8 14h3" />
      </svg>
    );
  }

  if (view === "mailboxes") {
    return (
      <svg
        viewBox="0 0 24 24"
        fill="none"
        stroke="currentColor"
        strokeWidth="1.8"
        strokeLinecap="round"
        strokeLinejoin="round"
        className={className}
        aria-hidden="true"
      >
        <rect x="3.5" y="5.5" width="17" height="13" rx="2.5" />
        <path d="m4.8 7 7.2 5.6L19.2 7" />
      </svg>
    );
  }

  return (
    <svg
      viewBox="0 0 24 24"
      fill="none"
      stroke="currentColor"
      strokeWidth="1.8"
      strokeLinecap="round"
      strokeLinejoin="round"
      className={className}
      aria-hidden="true"
    >
      <path d="M9 11a3 3 0 1 0-3-3 3 3 0 0 0 3 3Z" />
      <path d="M15.8 10.5a2.5 2.5 0 1 0-2.5-2.5 2.5 2.5 0 0 0 2.5 2.5Z" />
      <path d="M4.5 18a4.8 4.8 0 0 1 8.8-2.7" />
      <path d="M14.1 18a4 4 0 0 1 5.4-2.6" />
    </svg>
  );
}

function AdminNavigation({
  chargeFilter,
  currentView,
  domain,
  items,
  q,
  rangeDays,
}: {
  chargeFilter: KavenixAdminChargeFilter;
  currentView: AdminView;
  domain: string;
  items: AdminNavItem[];
  q: string;
  rangeDays: KavenixMarketingRangeDays;
}) {
  return (
    <nav className="space-y-1" aria-label="최고관리자 메뉴">
      {items.map((item) => {
        const active = currentView === item.view;

        return (
          <Link
            key={item.view}
            href={buildAdminHref({
              view: item.view,
              q,
              domain,
              chargeFilter,
              rangeDays: item.view === "analytics" ? rangeDays : undefined,
            })}
            className={`group flex min-h-10 w-full items-center gap-[6px] rounded-[10px] px-2 py-2 text-left text-[14px] font-medium transition-colors duration-150 ${
              active
                ? "bg-[#edf4ff] font-semibold text-[#2f6df6]"
                : "text-[#33445f] hover:bg-[#f4f6fa] hover:text-[#2f6df6]"
            }`}
          >
            <span
              className={`inline-flex h-7 w-7 shrink-0 items-center justify-center rounded-[8px] transition-colors ${
                active ? "text-[#2f6df6]" : "text-[#8390a8] group-hover:text-[#2f6df6]"
              }`}
            >
              <AdminViewIcon view={item.view} className="h-[17px] w-[17px]" />
            </span>
            <span className="min-w-0 flex-1 truncate">{item.label}</span>
            {typeof item.count === "number" ? (
              <span className={`shrink-0 text-[12px] font-semibold ${active ? "text-[#2f6df6]" : "text-[#70829f]"}`}>
                {item.count.toLocaleString("ko-KR")}
              </span>
            ) : null}
          </Link>
        );
      })}
    </nav>
  );
}

function AdminSidebar({
  chargeFilter,
  currentView,
  domain,
  items,
  q,
  rangeDays,
  userEmail,
}: {
  chargeFilter: KavenixAdminChargeFilter;
  currentView: AdminView;
  domain: string;
  items: AdminNavItem[];
  q: string;
  rangeDays: KavenixMarketingRangeDays;
  userEmail: string;
}) {
  return (
    <aside className="sticky top-0 hidden h-dvh min-h-0 w-[270px] shrink-0 self-start overflow-hidden border-r border-[#edf1f6] bg-white lg:flex lg:flex-col">
      <div className="shrink-0 border-b border-[#edf1f6] px-4 pb-4 pt-5">
        <p className="text-[12px] font-semibold uppercase tracking-[0.12em] text-[#7d8ca8]">Kavenix Admin</p>
        <p className="mt-2 truncate text-[18px] font-semibold tracking-[-0.04em] text-[#16233c]">
          최고관리자
        </p>
        <p className="mt-1 truncate text-[13px] text-[#6d7f9d]">{userEmail}</p>
      </div>
      <div className="min-h-0 flex-1 overflow-y-auto overscroll-contain px-3 py-3">
        <AdminNavigation
          chargeFilter={chargeFilter}
          currentView={currentView}
          domain={domain}
          items={items}
          q={q}
          rangeDays={rangeDays}
        />
      </div>
      <div className="shrink-0 border-t border-[#edf1f6] px-4 py-4 text-[12px] leading-5 text-[#7c8da8]">
        운영 데이터는 실시간 조회 기준으로 표시됩니다.
      </div>
    </aside>
  );
}

function AdminMobileMenu({
  chargeFilter,
  currentView,
  domain,
  items,
  q,
  rangeDays,
}: {
  chargeFilter: KavenixAdminChargeFilter;
  currentView: AdminView;
  domain: string;
  items: AdminNavItem[];
  q: string;
  rangeDays: KavenixMarketingRangeDays;
}) {
  const currentItem = items.find((item) => item.view === currentView) ?? items[0];

  return (
    <details className="group lg:hidden">
      <summary className="flex min-h-10 cursor-pointer list-none items-center justify-between gap-3 rounded-[10px] bg-[#f6f8fc] px-3 py-2 text-[#16233c] marker:hidden transition-colors hover:bg-[#f1f5fb] [&::-webkit-details-marker]:hidden">
        <span className="inline-flex min-w-0 items-center gap-2">
          <MenuIcon className="h-[18px] w-[18px] shrink-0 text-[#2f6df6]" />
          <span className="min-w-0">
            <span className="block truncate text-[14px] font-semibold">{currentItem.label}</span>
          </span>
        </span>
        <span className="h-2 w-2 rotate-45 border-b border-r border-[#7d8ca8] transition-transform group-open:rotate-[225deg]" />
      </summary>
      <div className="mt-2 border-y border-[#edf1f6] bg-white py-2">
        <AdminNavigation
          chargeFilter={chargeFilter}
          currentView={currentView}
          domain={domain}
          items={items}
          q={q}
          rangeDays={rangeDays}
        />
      </div>
    </details>
  );
}

function formatDateTime(value: string | null) {
  if (!value) {
    return "-";
  }

  return new Intl.DateTimeFormat("ko-KR", {
    year: "numeric",
    month: "2-digit",
    day: "2-digit",
    hour: "2-digit",
    minute: "2-digit",
  }).format(new Date(value));
}

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

function formatChargeAmount(value: number, currency: string) {
  const normalizedCurrency = currency.trim().toUpperCase();

  if (normalizedCurrency === "KRW") {
    return formatCurrency(value);
  }

  return new Intl.NumberFormat("en-US", {
    currency: normalizedCurrency || "USD",
    currencyDisplay: "narrowSymbol",
    maximumFractionDigits: 2,
    minimumFractionDigits: 2,
    style: "currency",
  }).format(value / 100);
}

function formatCancellationResult(value: string | null) {
  if (!value) {
    return "-";
  }

  try {
    const parsed = JSON.parse(value) as {
      cleanupError?: string | null;
      deletedAssetCount?: number;
      deletedManagedMemberCount?: number;
      deletedMessageCount?: number;
      refundedAmount?: number;
    };
    const parts: string[] = [];

    if (typeof parsed.deletedMessageCount === "number") {
      parts.push(`메시지 ${parsed.deletedMessageCount.toLocaleString("ko-KR")}건 정리`);
    }

    if (typeof parsed.deletedAssetCount === "number") {
      parts.push(`파일 ${parsed.deletedAssetCount.toLocaleString("ko-KR")}건 정리`);
    }

    if (typeof parsed.deletedManagedMemberCount === "number") {
      parts.push(`멤버 ${parsed.deletedManagedMemberCount.toLocaleString("ko-KR")}명 정리`);
    }

    if (typeof parsed.refundedAmount === "number" && parsed.refundedAmount > 0) {
      parts.push(`환불 ${formatCurrency(parsed.refundedAmount)}`);
    }

    if (parsed.cleanupError) {
      parts.push(`정리 오류: ${parsed.cleanupError}`);
    }

    return parts.length > 0 ? parts.join(" / ") : "처리 완료";
  } catch {
    return value;
  }
}

function formatCancellationReviewNote(value: string | null) {
  if (!value) {
    return null;
  }

  if (value === "policy-auto-withdrawal") {
    return "정책 기준 충족으로 자동 청약철회 처리";
  }

  return value;
}

function buildAdminHref(input: {
  chargeFilter?: KavenixAdminChargeFilter;
  domain?: string;
  marketingDrilldown?: KavenixMarketingDrilldown | null;
  q?: string;
  rangeDays?: KavenixMarketingRangeDays;
  view: AdminView;
}) {
  const searchParams = new URLSearchParams();
  searchParams.set("view", input.view);

  if (input.q?.trim()) {
    searchParams.set("q", input.q.trim());
  }

  if (input.domain?.trim()) {
    searchParams.set("domain", input.domain.trim());
  }

  if (input.chargeFilter && input.chargeFilter !== "all") {
    searchParams.set("chargeFilter", input.chargeFilter);
  }

  if (input.rangeDays) {
    searchParams.set("range", String(input.rangeDays));
  }

  if (input.marketingDrilldown) {
    searchParams.set("drill", input.marketingDrilldown.dimension);
    searchParams.set("drillValue", input.marketingDrilldown.value);
  }

  const query = searchParams.toString();
  return query ? `/kavenix?${query}` : "/kavenix";
}

function buildAdminMailboxHref(
  mailboxId: number,
  options?: {
    folder?: string;
    messageId?: number | null;
    page?: number;
  },
) {
  const searchParams = new URLSearchParams({
    mailbox: String(mailboxId),
    view: "mailboxes",
  });

  if (options?.folder) {
    searchParams.set("mailFolder", options.folder);
  }

  if (options?.messageId) {
    searchParams.set("mailMessage", String(options.messageId));
  }

  if (options?.page && options.page > 1) {
    searchParams.set("mailPage", String(options.page));
  }

  return `/kavenix?${searchParams.toString()}`;
}

function adminMailboxFolderLabel(systemName: string) {
  if (systemName === "inbox") return "받은메일";
  if (systemName === "sent") return "보낸메일";
  if (systemName === "drafts") return "임시보관함";
  if (systemName === "spam") return "스팸함";
  if (systemName === "trash") return "휴지통";
  return "메일함";
}

function adminMailboxSenderLabel(message: MailMessageSummary) {
  return message.direction === "outbound"
    ? message.toAddresses || "(받는 사람 없음)"
    : message.fromName || message.fromAddress;
}

function rewriteAdminMailboxAttachmentSources(
  bodyHtml: string,
  mailboxId: number,
) {
  return bodyHtml.replace(
    /\/api\/mailbox\/attachment\?/g,
    `/api/kavenix/mailbox/attachment?mailbox=${mailboxId}&amp;`,
  );
}

function buildAdminMailboxAttachmentHref(input: {
  attachmentIndex: number;
  mailboxId: number;
  messageId: number;
  mode?: "download" | "inline";
}) {
  const searchParams = new URLSearchParams({
    index: String(input.attachmentIndex),
    mailbox: String(input.mailboxId),
    message: String(input.messageId),
    mode: input.mode ?? "download",
  });

  return `/api/kavenix/mailbox/attachment?${searchParams.toString()}`;
}

function badgeClass(tone: "blue" | "green" | "amber" | "rose" | "slate") {
  if (tone === "green") {
    return "om-badge-success";
  }

  if (tone === "amber") {
    return "om-badge-warning";
  }

  if (tone === "rose") {
    return "om-badge-danger";
  }

  if (tone === "blue") {
    return "om-badge-info";
  }

  return "om-badge-muted";
}

type ChargeStageVariant =
  | "payment-success"
  | "payment-failed"
  | "payment-requested"
  | "payment-skipped"
  | "refund-processing"
  | "refund-full"
  | "refund-partial"
  | "withdrawal-pending"
  | "withdrawal-approved"
  | "withdrawal-rejected"
  | "muted";

function chargeStageBadgeClass(variant: ChargeStageVariant) {
  if (variant === "payment-success") {
    return "border-[#bfdbfe] bg-[#eff6ff] text-[#1d4ed8]";
  }

  if (variant === "refund-full") {
    return "border-[#ddd6fe] bg-[#f5f3ff] text-[#6d28d9]";
  }

  if (variant === "refund-partial") {
    return "border-[#bae6fd] bg-[#f0f9ff] text-[#0369a1]";
  }

  if (variant === "refund-processing" || variant === "withdrawal-pending") {
    return "border-[#fed7aa] bg-[#fff7ed] text-[#c2410c]";
  }

  if (variant === "withdrawal-approved") {
    return "border-[#c7d2fe] bg-[#eef2ff] text-[#4338ca]";
  }

  if (variant === "payment-failed" || variant === "withdrawal-rejected") {
    return "border-[#fecdd3] bg-[#fff1f2] text-[#be123c]";
  }

  if (variant === "payment-requested") {
    return "border-[#d8e4ff] bg-[#f5f8ff] text-[#315fce]";
  }

  if (variant === "payment-skipped") {
    return "border-[#fde68a] bg-[#fffbeb] text-[#a16207]";
  }

  return "border-[#e4eaf4] bg-white text-[#5f718e]";
}

function chargeStageDotClass(variant: ChargeStageVariant) {
  if (variant === "payment-success" || variant === "payment-requested") {
    return "bg-[#2f6df6]";
  }

  if (variant === "refund-full") {
    return "bg-[#7c3aed]";
  }

  if (variant === "refund-partial") {
    return "bg-[#0284c7]";
  }

  if (variant === "refund-processing" || variant === "withdrawal-pending" || variant === "payment-skipped") {
    return "bg-[#f97316]";
  }

  if (variant === "withdrawal-approved") {
    return "bg-[#4f46e5]";
  }

  if (variant === "payment-failed" || variant === "withdrawal-rejected") {
    return "bg-[#e11d48]";
  }

  return "bg-[#94a3b8]";
}

function domainStatusMeta(status: KavenixAdminUserRow["latestDomainStatus"] | KavenixAdminDomainRow["domainStatus"]) {
  if (status === "verified") {
    return { label: "검증 완료", tone: "green" as const };
  }

  if (status === "failed") {
    return { label: "점검 필요", tone: "rose" as const };
  }

  if (status === "pending") {
    return { label: "대기 중", tone: "amber" as const };
  }

  return { label: "-", tone: "slate" as const };
}

function mailboxStatusMeta(
  status:
    | KavenixAdminUserRow["latestMailboxStatus"]
    | KavenixAdminDomainRow["mailboxStatus"]
    | KavenixAdminMailboxRow["status"],
) {
  if (status === "active") {
    return { label: "활성", tone: "green" as const };
  }

  if (status === "pending_dns") {
    return { label: "DNS 대기", tone: "amber" as const };
  }

  if (status === "disabled") {
    return { label: "사용 중지", tone: "rose" as const };
  }

  return { label: "-", tone: "slate" as const };
}

function provisioningStatusMeta(status: KavenixAdminDomainRow["provisioningStatus"]) {
  if (status === "ready") {
    return { label: "메일 서버 정상", tone: "green" as const };
  }

  if (status === "mailcow-domain-missing") {
    return { label: "Mailcow 도메인 누락", tone: "rose" as const };
  }

  if (status === "mailcow-mailbox-missing") {
    return { label: "대표 메일함 누락", tone: "rose" as const };
  }

  if (status === "database-mailbox-missing") {
    return { label: "DB 메일함 누락", tone: "rose" as const };
  }

  if (status === "state-mismatch") {
    return { label: "연결 상태 불일치", tone: "rose" as const };
  }

  if (status === "unknown") {
    return { label: "메일 서버 조회 실패", tone: "amber" as const };
  }

  return { label: "정리됨", tone: "slate" as const };
}

function billingStatusMeta(status: KavenixAdminUserRow["subscriptionStatus"] | KavenixAdminDomainRow["subscriptionStatus"]) {
  if (status === "active") {
    return { label: "자동결제 활성", tone: "green" as const };
  }

  if (status === "paused") {
    return { label: "일시중지", tone: "amber" as const };
  }

  if (status === "cancelled") {
    return { label: "해지", tone: "rose" as const };
  }

  if (status === "pending") {
    return { label: "등록 대기", tone: "blue" as const };
  }

  return { label: "미등록", tone: "slate" as const };
}

function chargeStatusMeta(
  status:
    | KavenixAdminUserRow["lastChargeStatus"]
    | KavenixAdminDomainRow["lastChargeStatus"]
    | KavenixAdminChargeRow["chargeStatus"],
) {
  if (status === "success") {
    return { label: "성공", tone: "green" as const };
  }

  if (status === "failed") {
    return { label: "실패", tone: "rose" as const };
  }

  if (status === "requested") {
    return { label: "요청됨", tone: "blue" as const };
  }

  if (status === "skipped") {
    return { label: "건너뜀", tone: "amber" as const };
  }

  return { label: "-", tone: "slate" as const };
}

function refundStateMeta(state: KavenixAdminChargeRefundState) {
  if (state === "processing") {
    return { label: "환불 처리 중", tone: "amber" as const };
  }

  if (state === "refunded") {
    return { label: "전액 환불 완료", tone: "green" as const };
  }

  if (state === "partial") {
    return { label: "부분 환불", tone: "blue" as const };
  }

  return { label: "환불 전", tone: "slate" as const };
}

function latestRefundMeta(status: KavenixAdminChargeRow["latestRefundStatus"]) {
  if (status === "success") {
    return { label: "최근 환불 성공", tone: "green" as const };
  }

  if (status === "failed") {
    return { label: "최근 환불 실패", tone: "rose" as const };
  }

  if (status === "pending") {
    return { label: "환불 대기", tone: "amber" as const };
  }

  return { label: "-", tone: "slate" as const };
}

function cancellationReviewMeta(row: KavenixAdminChargeRow) {
  if (!row.cancellationRequestId || !row.cancellationReviewStatus) {
    return null;
  }

  if (row.cancellationRequestStatus === "processing") {
    return { label: "청약철회 진행", tone: "amber" as const };
  }

  if (row.cancellationReviewStatus === "pending_review") {
    return { label: "청약철회 신청", tone: "amber" as const };
  }

  if (row.cancellationReviewStatus === "approved_partial") {
    return row.cancellationRequestStatus === "completed"
      ? { label: "부분 환불 완료", tone: "green" as const }
      : { label: "부분 환불 승인", tone: "blue" as const };
  }

  if (row.cancellationReviewStatus === "approved_full") {
    return row.cancellationRequestStatus === "completed"
      ? { label: "청약철회 완료", tone: "green" as const }
      : { label: "청약철회 승인", tone: "blue" as const };
  }

  if (row.cancellationReviewStatus === "rejected") {
    return { label: "청약철회 반려", tone: "rose" as const };
  }

  if (row.cancellationReviewStatus === "cancelled_by_user") {
    return { label: "청약철회 요청 취소", tone: "slate" as const };
  }

  return { label: "청약철회 연결", tone: "slate" as const };
}

function chargeStageMeta(row: KavenixAdminChargeRow) {
  const cancellationMeta = cancellationReviewMeta(row);

  if (cancellationMeta) {
    if (row.cancellationReviewStatus === "rejected") {
      return { ...cancellationMeta, variant: "withdrawal-rejected" as const };
    }

    if (row.cancellationReviewStatus === "cancelled_by_user") {
      return { ...cancellationMeta, variant: "muted" as const };
    }

    if (row.cancellationRequestStatus === "completed") {
      return {
        ...cancellationMeta,
        variant: row.cancellationReviewStatus === "approved_partial" ? ("refund-partial" as const) : ("refund-full" as const),
      };
    }

    if (row.cancellationReviewStatus === "approved_partial" || row.cancellationReviewStatus === "approved_full") {
      return { ...cancellationMeta, variant: "withdrawal-approved" as const };
    }

    return { ...cancellationMeta, variant: "withdrawal-pending" as const };
  }

  if (row.latestRefundStatus === "pending" || row.refundState === "processing") {
    return { label: "환불 진행", tone: "amber" as const, variant: "refund-processing" as const };
  }

  if (row.refundState === "refunded") {
    return { label: "전액 환불 완료", tone: "green" as const, variant: "refund-full" as const };
  }

  if (row.refundState === "partial") {
    return { label: "부분 환불", tone: "blue" as const, variant: "refund-partial" as const };
  }

  if (row.chargeStatus === "success") {
    return { label: "결제완료", tone: "green" as const, variant: "payment-success" as const };
  }

  if (row.chargeStatus === "failed") {
    return { label: "결제 실패", tone: "rose" as const, variant: "payment-failed" as const };
  }

  if (row.chargeStatus === "requested") {
    return { label: "결제 요청", tone: "blue" as const, variant: "payment-requested" as const };
  }

  if (row.chargeStatus === "skipped") {
    return { label: "청구 건너뜀", tone: "amber" as const, variant: "payment-skipped" as const };
  }

  return { label: "-", tone: "slate" as const, variant: "muted" as const };
}

function SummaryRail({ className = "", summary }: { className?: string; summary: KavenixAdminSummary }) {
  const items = [
    ["전체 사용자", `${summary.totalUsers.toLocaleString("ko-KR")}명`],
    ["연결 도메인", `${summary.totalDomains.toLocaleString("ko-KR")}개`],
    ["활성 멤버", `${summary.activeMembers.toLocaleString("ko-KR")}명`],
    ["월 예상 매출", formatCurrency(summary.expectedMonthlyRevenue)],
    ["활성 정기결제", `${summary.activeSubscriptions.toLocaleString("ko-KR")}건`],
    ["최근 30일 성공 청구", `${summary.successfulCharges30d.toLocaleString("ko-KR")}건`],
  ] as const;

  return (
    <div className={`${className} border-b border-[#edf1f6] bg-white`}>
      <div className={`flex overflow-x-auto ${ADMIN_X_PADDING}`}>
        {items.map(([label, value], index) => (
          <div
            key={label}
            className={`min-w-[154px] shrink-0 py-3 pr-6 ${
              index !== 0 ? "border-l border-[#edf2fb] pl-6" : ""
            }`}
          >
            <p className="text-[12px] font-medium text-[#7c879b]">
              {label}
            </p>
            <p className="mt-1 text-[16px] font-semibold tracking-[-0.03em] text-[#16233c]">
              {value}
            </p>
          </div>
        ))}
      </div>
    </div>
  );
}

function formatConversionRate(value: number, base: number) {
  if (base <= 0) {
    return "-";
  }

  return `${((value / base) * 100).toFixed(1)}%`;
}

function MarketingRangeSelector({
  drilldown,
  rangeDays,
}: {
  drilldown: KavenixMarketingDrilldown | null;
  rangeDays: KavenixMarketingRangeDays;
}) {
  return (
    <div className="flex items-center gap-1.5" aria-label="유입 분석 기간">
      {([7, 30, 90] as const).map((days) => {
        const active = days === rangeDays;

        return (
          <Link
            key={days}
            href={buildAdminHref({ marketingDrilldown: drilldown, rangeDays: days, view: "analytics" })}
            className={`inline-flex h-9 items-center rounded-[10px] px-3 text-[13px] font-semibold transition-colors ${
              active
                ? "bg-[#edf4ff] text-[#2f6df6]"
                : "text-[#6d7e9a] hover:bg-[#f5f8fc] hover:text-[#2f6df6]"
            }`}
          >
            최근 {days}일
          </Link>
        );
      })}
    </div>
  );
}

function MarketingFunnelRail({ analytics }: { analytics: KavenixMarketingAnalytics }) {
  const { metrics } = analytics;
  const steps = [
    {
      description: "공개 페이지 방문",
      drilldown: { dimension: "funnel", value: "landing" } satisfies KavenixMarketingDrilldown,
      label: "유입 방문자",
      value: metrics.landingVisitors,
    },
    {
      description: `유입 대비 ${formatConversionRate(metrics.signups, metrics.landingVisitors)}`,
      drilldown: { dimension: "funnel", value: "signup" } satisfies KavenixMarketingDrilldown,
      label: "가입 완료",
      value: metrics.signups,
    },
    {
      description: `가입 대비 ${formatConversionRate(metrics.domainVerified, metrics.signups)}`,
      drilldown: { dimension: "funnel", value: "domain" } satisfies KavenixMarketingDrilldown,
      label: "도메인 연결",
      value: metrics.domainVerified,
    },
    {
      description: `연결 대비 ${formatConversionRate(metrics.growthPlanStarted, metrics.domainVerified)}`,
      drilldown: { dimension: "funnel", value: "growth" } satisfies KavenixMarketingDrilldown,
      label: "성장플랜 전환",
      value: metrics.growthPlanStarted,
    },
  ] as const;

  return (
    <section className="border-b border-[#edf1f6] bg-white">
      <div className={`flex overflow-x-auto ${ADMIN_X_PADDING}`}>
        {steps.map((step, index) => (
          <Link
            key={step.label}
            href={buildAdminHref({ marketingDrilldown: step.drilldown, rangeDays: analytics.rangeDays, view: "analytics" })}
            className={`group min-w-[170px] shrink-0 py-4 pr-6 transition-colors hover:bg-[#fafcff] ${
              index > 0 ? "border-l border-[#edf2fb] pl-6" : ""
            }`}
          >
            <p className="text-[12px] font-medium text-[#7c879b] transition-colors group-hover:text-[#2f6df6]">{step.label}</p>
            <p className="mt-1.5 text-[24px] font-semibold tracking-[-0.05em] text-[#16233c]">
              {step.value.toLocaleString("ko-KR")}
            </p>
            <p className="mt-1 text-[12px] text-[#70819d]">{step.description}</p>
            <span className="mt-2 inline-flex text-[11px] font-semibold text-[#2f6df6] opacity-0 transition-opacity group-hover:opacity-100">상세 분석 보기</span>
          </Link>
        ))}
      </div>
    </section>
  );
}

const PRODUCT_FUNNEL_GROUPS = [
  {
    key: "signup",
    title: "가입 흐름",
    eventTypes: new Set([
      "signup_form_viewed",
      "signup_recovery_sent",
      "signup_recovery_verified",
      "signup_submitted",
      "signup_failed",
      "signup_completed",
    ]),
  },
  {
    key: "domain",
    title: "도메인 연결 흐름",
    eventTypes: new Set([
      "dns_setup_viewed",
      "dns_wizard_step_viewed",
      "dns_record_confirmed",
      "dns_verification_attempted",
      "dns_verification_failed",
      "domain_verified",
    ]),
  },
  {
    key: "billing",
    title: "결제 흐름",
    eventTypes: new Set([
      "payment_method_added",
      "growth_plan_started",
      "purchase_completed",
    ]),
  },
] as const;

const PRODUCT_FUNNEL_EVENT_ORDER: Record<string, number> = {
  signup_form_viewed: 10,
  signup_recovery_sent: 20,
  signup_recovery_verified: 30,
  signup_submitted: 40,
  signup_failed: 45,
  signup_completed: 50,
  dns_setup_viewed: 100,
  dns_wizard_step_viewed: 110,
  dns_record_confirmed: 200,
  dns_verification_attempted: 250,
  dns_verification_failed: 260,
  domain_verified: 270,
  payment_method_added: 300,
  growth_plan_started: 310,
  purchase_completed: 320,
};

const PRODUCT_FUNNEL_DETAIL_ORDER: Record<string, number> = {
  provider: 1,
  website_connection: 2,
  website_hosting: 3,
  dns_location: 4,
  domain_registration: 5,
  record_mx_1: 11,
  record_spf_2: 12,
  record_dkim_3: 13,
  record_dmarc_4: 14,
  verification: 20,
};

function productFunnelLabel(eventType: string, detail: string | null) {
  const recordName = detail?.includes("_mx_")
    ? "MX"
    : detail?.includes("_spf_")
      ? "SPF"
      : detail?.includes("_dkim_")
        ? "DKIM"
        : detail?.includes("_dmarc_")
          ? "DMARC"
          : null;
  if (eventType === "signup_form_viewed") return "가입 화면 진입";
  if (eventType === "signup_recovery_sent") return "보조 이메일 인증 발송";
  if (eventType === "signup_recovery_verified") return "보조 이메일 인증 완료";
  if (eventType === "signup_submitted") return "가입 제출";
  if (eventType === "signup_failed") return `가입 실패${detail ? ` · ${detail}` : ""}`;
  if (eventType === "signup_completed") return "가입 완료";
  if (eventType === "dns_setup_viewed") return "도메인 연결 화면 진입";
  if (eventType === "dns_wizard_step_viewed") {
    if (detail === "provider") return "도메인 업체 선택";
    if (detail === "website_connection") return "웹사이트 연결 여부";
    if (detail === "website_hosting") return "웹사이트 호스팅 선택";
    if (detail === "dns_location") return "DNS 설정 위치 확인";
    if (detail === "domain_registration") return "도메인 정보 저장";
    if (detail === "verification") return "DNS 검증 단계 도달";
    return recordName ? `${recordName} 레코드 안내 진입` : "DNS 레코드 안내 진입";
  }
  if (eventType === "dns_record_confirmed") {
    return recordName ? `${recordName} 저장 확인` : "DNS 레코드 저장 확인";
  }
  if (eventType === "dns_verification_attempted") return "연결 검증 시도";
  if (eventType === "dns_verification_failed") {
    return `연결 검증 실패${recordName ? ` · ${recordName}` : ""}`;
  }
  if (eventType === "domain_verified") return "도메인 연결 완료";
  if (eventType === "payment_method_added") return "결제수단 등록";
  if (eventType === "growth_plan_started") return "성장플랜 활성화";
  if (eventType === "purchase_completed") return "결제 완료";
  return eventType;
}

function MarketingProductFunnel({ analytics }: { analytics: KavenixMarketingAnalytics }) {
  const sortedRows = [...analytics.productFunnel].sort((left, right) => {
    const eventDifference =
      (PRODUCT_FUNNEL_EVENT_ORDER[left.eventType] ?? 999) -
      (PRODUCT_FUNNEL_EVENT_ORDER[right.eventType] ?? 999);
    if (eventDifference !== 0) return eventDifference;
    return (
      (PRODUCT_FUNNEL_DETAIL_ORDER[left.detail ?? ""] ?? 999) -
      (PRODUCT_FUNNEL_DETAIL_ORDER[right.detail ?? ""] ?? 999)
    );
  });

  return (
    <section className="border-b border-[#edf1f6] bg-[#fbfcff] px-3 py-5 sm:px-4 lg:px-8">
      <div className="flex flex-col gap-1 sm:flex-row sm:items-end sm:justify-between">
        <div>
          <h2 className="text-[14px] font-semibold tracking-[-0.03em] text-[#16233c]">
            가입·도메인·결제 세부 퍼널
          </h2>
          <p className="mt-1 text-[12px] leading-5 text-[#70819d]">
            단계별 고유 사용자와 재시도 횟수입니다. 새 측정 배포 이후 데이터부터 정확히 비교됩니다.
          </p>
        </div>
        <p className="text-[11px] text-[#93a0b4]">메일 내용·DNS 값·카드번호는 수집하지 않음</p>
      </div>
      <div className="mt-4 grid overflow-hidden rounded-[16px] border border-[#e2e9f4] bg-white lg:grid-cols-3">
        {PRODUCT_FUNNEL_GROUPS.map((group, groupIndex) => {
          const rows = sortedRows.filter((row) => group.eventTypes.has(row.eventType));
          return (
            <div key={group.key} className={groupIndex > 0 ? "border-t border-[#e9eef6] lg:border-l lg:border-t-0" : ""}>
              <h3 className="border-b border-[#edf1f6] bg-[#f8faff] px-4 py-3 text-[12px] font-semibold text-[#344767]">
                {group.title}
              </h3>
              {rows.length > 0 ? (
                <div>
                  {rows.map((row) => {
                    const isFailure = row.eventType.endsWith("_failed");
                    return (
                      <div key={`${row.eventType}:${row.detail ?? ""}`} className="flex items-center justify-between gap-3 border-b border-[#f0f3f8] px-4 py-2.5 last:border-b-0">
                        <p className={`min-w-0 truncate text-[12px] ${isFailure ? "font-semibold text-[#c34f68]" : "text-[#52647f]"}`} title={productFunnelLabel(row.eventType, row.detail)}>
                          {productFunnelLabel(row.eventType, row.detail)}
                        </p>
                        <KavenixMarketingProductFunnelDetailButton
                          actorCount={row.actors}
                          detail={row.detail}
                          eventCount={row.events}
                          eventType={row.eventType}
                          label={productFunnelLabel(row.eventType, row.detail)}
                          rangeDays={analytics.rangeDays}
                        />
                      </div>
                    );
                  })}
                </div>
              ) : (
                <p className="px-4 py-7 text-center text-[12px] text-[#91a0b6]">새 이벤트 수집 대기 중</p>
              )}
            </div>
          );
        })}
      </div>
    </section>
  );
}

function MarketingTrend({ analytics }: { analytics: KavenixMarketingAnalytics }) {
  if (analytics.dailyVisitors.length === 0) {
    return (
      <div className="flex h-[176px] items-center justify-center border-t border-[#edf1f6] text-[13px] text-[#7c8da8]">
        아직 집계된 유입이 없습니다.
      </div>
    );
  }

  const maxVisitors = Math.max(
    1,
    ...analytics.dailyVisitors.map((row) => row.visitors),
  );

  return (
    <div className="border-t border-[#edf1f6] px-3 pb-3 pt-5 sm:px-4 lg:px-8">
      <div className="flex h-[128px] min-w-[420px] items-end gap-1.5">
        {analytics.dailyVisitors.map((row) => {
          const height = Math.max(5, Math.round((row.visitors / maxVisitors) * 100));

          return (
            <div key={row.day} className="flex min-w-0 flex-1 flex-col items-center justify-end gap-2">
              <div
                className="w-full rounded-t-[4px] bg-[#8bb2ff] transition-colors hover:bg-[#2f6df6]"
                style={{ height: `${height}%` }}
                title={`${row.day} ${row.visitors.toLocaleString("ko-KR")}명`}
              />
              <span className="whitespace-nowrap text-[10px] text-[#8795ad]">{row.day}</span>
            </div>
          );
        })}
      </div>
    </div>
  );
}

function MarketingTrafficList({
  dimension,
  heading,
  rangeDays,
  rows,
}: {
  dimension: KavenixMarketingDrilldownDimension;
  heading: string;
  rangeDays: KavenixMarketingRangeDays;
  rows: Array<{ label?: string; path?: string; visitors: number }>;
}) {
  return (
    <section className="min-w-0">
      <div className="border-b border-[#edf1f6] px-3 py-3 sm:px-4 lg:px-8">
        <h2 className="text-[14px] font-semibold tracking-[-0.03em] text-[#16233c]">{heading}</h2>
      </div>
      {rows.length > 0 ? (
        <div>
          {rows.map((row, index) => {
            const label = row.path ?? row.label ?? "-";

            const drilldown = {
              dimension,
              value: label,
            } satisfies KavenixMarketingDrilldown;

            return (
              <Link
                key={`${label}-${index}`}
                href={buildAdminHref({ marketingDrilldown: drilldown, rangeDays, view: "analytics" })}
                className="flex items-center justify-between gap-4 border-b border-[#edf1f6] px-3 py-3 text-[13px] last:border-b-0 sm:px-4 lg:px-8"
              >
                <span className="min-w-0 truncate font-medium text-[#30425f] transition-colors hover:text-[#2f6df6]" title={label}>
                  {label}
                </span>
                <span className="shrink-0 font-semibold text-[#2f6df6]">
                  {row.visitors.toLocaleString("ko-KR")}명
                </span>
              </Link>
            );
          })}
        </div>
      ) : (
        <div className="px-3 py-8 text-[13px] text-[#7c8da8] sm:px-4 lg:px-8">
          집계된 데이터가 없습니다.
        </div>
      )}
    </section>
  );
}

function MarketingFunnelAudience({ drilldown }: { drilldown: NonNullable<KavenixMarketingAnalytics["drilldown"]> }) {
  return (
    <section className="border-t border-[#edf1f6]">
      <div className={`flex flex-col gap-3 border-b border-[#edf1f6] py-3 ${ADMIN_X_PADDING}`}>
        <div className="flex flex-col gap-2 sm:flex-row sm:items-start sm:justify-between">
          <h3 className="text-[14px] font-semibold tracking-[-0.03em] text-[#16233c]">{drilldown.audienceTitle}</h3>
          <KavenixMarketingPagination pagination={drilldown.pagination} />
        </div>
        <div>
          <p className="mt-1 text-[12px] text-[#7183a1]">{drilldown.audienceDescription}</p>
          <p className="mt-1 text-[12px] text-[#7183a1]">UTM, 전달된 리퍼러, 인앱 식별 정보 순으로 표시합니다. 인앱 추정은 앱 정보에 따른 분류이며, 전달되지 않은 게시글 주소는 알 수 없습니다. 이전에 잘못 수집된 내부 IP는 표시하지 않습니다.</p>
        </div>
      </div>
      {drilldown.audience.length > 0 ? (
        <div className="overflow-x-auto">
          <table className="w-full min-w-[1080px] border-collapse text-left">
            <thead className="border-b border-[#edf1f6] text-[12px] font-semibold text-[#7c879b]">
              <tr>
                <th className="px-3 py-2.5 sm:px-4 lg:px-8">시각</th>
                <th className="px-3 py-2.5">방문자·계정</th>
                <th className="px-3 py-2.5">도메인</th>
                <th className="px-3 py-2.5">랜딩</th>
                <th className="px-3 py-2.5">유입 경로 / 리퍼러</th>
                <th className="px-3 py-2.5 sm:px-4 lg:px-8">IP 주소</th>
              </tr>
            </thead>
            <tbody>
              {drilldown.audience.map((entry, index) => {
                const identity = entry.email ?? (entry.visitorId ? `익명 방문자 ${entry.visitorId.slice(0, 12)}` : "식별 정보 없음");
                const detail = [entry.companyName, entry.country].filter(Boolean).join(" · ");

                return (
                  <tr key={`${entry.occurredAt ?? "unknown"}-${entry.email ?? entry.visitorId ?? "visitor"}-${index}`} className="border-b border-[#edf1f6] text-[13px] text-[#33445f] last:border-b-0">
                    <td className="whitespace-nowrap px-3 py-1.5 text-[#7183a1] sm:px-4 lg:px-8">{formatDateTime(entry.occurredAt)}</td>
                    <td className="max-w-[240px] px-3 py-1.5">
                      <p className="truncate font-medium" title={identity}>{identity}</p>
                      {detail ? <p className="mt-0.5 truncate text-[11px] text-[#7d8da8]">{detail}</p> : null}
                    </td>
                    <td className="max-w-[180px] truncate px-3 py-1.5" title={entry.domain ?? "-"}>{entry.domain ?? "-"}</td>
                    <td className="max-w-[180px] truncate px-3 py-1.5" title={entry.landingPath ?? "-"}>{entry.landingPath ?? "-"}</td>
                    <td className="max-w-[260px] px-3 py-1.5">
                      <p className="truncate font-medium" title={entry.channel}>{entry.channel}</p>
                      <p className="mt-0.5 truncate text-[11px] text-[#7d8da8]" title={entry.referrer ?? "리퍼러 미전달"}>{entry.referrer ?? "리퍼러 미전달"}</p>
                    </td>
                    <td className="whitespace-nowrap px-3 py-1.5 sm:px-4 lg:px-8">
                      {entry.ipAddress ? (
                        <span title={entry.ipAddressApproximate ? "이전 수집분은 네트워크 대역만 보관되어 있습니다." : undefined}>
                          {entry.ipAddress}{entry.ipAddressApproximate ? " · 이전 대역" : ""}
                        </span>
                      ) : "확인 불가"}
                    </td>
                  </tr>
                );
              })}
            </tbody>
          </table>
        </div>
      ) : (
        <p className={`py-8 text-[13px] text-[#7284a4] ${ADMIN_X_PADDING}`}>선택한 기간에 표시할 대상이 없습니다.</p>
      )}
    </section>
  );
}

function MarketingDrilldownPanel({
  drilldown,
  rangeDays,
}: {
  drilldown: NonNullable<KavenixMarketingAnalytics["drilldown"]>;
  rangeDays: KavenixMarketingRangeDays;
}) {
  const metrics = [
    ["유입 방문자", drilldown.metrics.landingVisitors],
    ["가입 완료", drilldown.metrics.signups],
    ["도메인 연결", drilldown.metrics.domainVerified],
    ["성장플랜 전환", drilldown.metrics.growthPlanStarted],
    ["관측 IP", drilldown.metrics.networks],
  ] as const;
  const breakdownHeading = drilldown.dimension === "page" ? "이 페이지의 유입 경로" : "이 경로의 랜딩 페이지";

  if (drilldown.dimension === "funnel") {
    return (
      <section className="border-b border-[#edf1f6] bg-white">
        <div className={`border-b border-[#edf1f6] py-4 ${ADMIN_X_PADDING}`}>
          <div className="min-w-0">
            <Link
              href={buildAdminHref({ rangeDays, view: "analytics" })}
              className="-ml-1 inline-flex h-7 items-center gap-1 rounded-[8px] px-1 text-[12px] font-semibold text-[#607493] transition-colors hover:text-[#2f6df6]"
            >
              <ArrowLeftIcon className="h-[15px] w-[15px]" />
              <span>돌아가기</span>
            </Link>
            <p className="mt-2 text-[12px] font-semibold text-[#2f6df6]">퍼널 상세</p>
            <h2 className="mt-1 truncate text-[16px] font-semibold tracking-[-0.04em] text-[#16233c]">{drilldown.label}</h2>
            <p className="mt-1.5 text-[12px] leading-5 text-[#70819d]">선택한 퍼널 단계의 실제 대상과 유입 정보를 기간 기준으로 확인합니다.</p>
          </div>
        </div>
        <div className={`flex overflow-x-auto border-b border-[#edf1f6] ${ADMIN_X_PADDING}`}>
          {metrics.map(([label, value], index) => (
            <div key={label} className={`min-w-[154px] shrink-0 py-3.5 pr-6 ${index > 0 ? "border-l border-[#edf2fb] pl-6" : ""}`}>
              <p className="text-[12px] font-medium text-[#7c879b]">{label}</p>
              <p className="mt-1 text-[21px] font-semibold tracking-[-0.05em] text-[#16233c]">{value.toLocaleString("ko-KR")}</p>
            </div>
          ))}
        </div>
        <MarketingFunnelAudience drilldown={drilldown} />
      </section>
    );
  }

  return (
    <section className="border-b border-[#edf1f6] bg-white">
      <div className={`border-b border-[#edf1f6] py-4 ${ADMIN_X_PADDING}`}>
        <div className="min-w-0">
          <Link
            href={buildAdminHref({ rangeDays, view: "analytics" })}
            className="-ml-1 inline-flex h-7 items-center gap-1 rounded-[8px] px-1 text-[12px] font-semibold text-[#607493] transition-colors hover:text-[#2f6df6]"
          >
            <ArrowLeftIcon className="h-[15px] w-[15px]" />
            <span>돌아가기</span>
          </Link>
          <p className="mt-2 text-[12px] font-semibold text-[#2f6df6]">유입 상세</p>
          <h2 className="mt-1 truncate text-[16px] font-semibold tracking-[-0.04em] text-[#16233c]" title={drilldown.label}>
            {drilldown.label}
          </h2>
          <p className="mt-1.5 text-[12px] leading-5 text-[#70819d]">
            같은 방문자 ID의 가입, 도메인 연결, 성장플랜 전환을 기간 안에서 함께 계산합니다.
          </p>
        </div>
      </div>

      <div className={`flex overflow-x-auto border-b border-[#edf1f6] ${ADMIN_X_PADDING}`}>
        {metrics.map(([label, value], index) => (
          <div key={label} className={`min-w-[154px] shrink-0 py-3.5 pr-6 ${index > 0 ? "border-l border-[#edf2fb] pl-6" : ""}`}>
            <p className="text-[12px] font-medium text-[#7c879b]">{label}</p>
            <p className="mt-1 text-[21px] font-semibold tracking-[-0.05em] text-[#16233c]">{value.toLocaleString("ko-KR")}</p>
            <p className="mt-1 text-[11px] text-[#7183a1]">
              {label === "유입 방문자" ? "선택 유입 기준" : `유입 대비 ${formatConversionRate(value, drilldown.metrics.landingVisitors)}`}
            </p>
          </div>
        ))}
      </div>

      <div className="grid lg:grid-cols-[minmax(0,1fr)_320px]">
        <div className="min-w-0 border-b border-[#edf1f6] lg:border-b-0">
          <div className="border-b border-[#edf1f6] px-3 py-3 sm:px-4 lg:px-8">
            <h3 className="text-[14px] font-semibold tracking-[-0.03em] text-[#16233c]">일별 전환 흐름</h3>
          </div>
          {drilldown.daily.length > 0 ? (
            <div className="overflow-x-auto">
              <table className="w-full min-w-[620px] border-collapse text-left">
                <thead className="border-b border-[#edf1f6] text-[12px] font-semibold text-[#7c879b]">
                  <tr>
                    <th className="px-3 py-2.5 sm:px-4 lg:px-8">날짜</th>
                    <th className="px-3 py-2.5 text-right">방문</th>
                    <th className="px-3 py-2.5 text-right">가입</th>
                    <th className="px-3 py-2.5 text-right">도메인</th>
                    <th className="px-3 py-2.5 text-right sm:px-4 lg:px-8">성장플랜</th>
                  </tr>
                </thead>
                <tbody>
                  {drilldown.daily.map((row) => (
                    <tr key={row.day} className="border-b border-[#edf1f6] text-[13px] text-[#33445f] last:border-b-0">
                      <td className="px-3 py-3 font-medium sm:px-4 lg:px-8">{row.day}</td>
                      <td className="px-3 py-3 text-right">{row.visitors.toLocaleString("ko-KR")}</td>
                      <td className="px-3 py-3 text-right">{row.signups.toLocaleString("ko-KR")}</td>
                      <td className="px-3 py-3 text-right">{row.domainVerified.toLocaleString("ko-KR")}</td>
                      <td className="px-3 py-3 text-right font-semibold text-[#2f6df6] sm:px-4 lg:px-8">{row.growthPlanStarted.toLocaleString("ko-KR")}</td>
                    </tr>
                  ))}
                </tbody>
              </table>
            </div>
          ) : (
            <p className="px-3 py-8 text-[13px] text-[#7284a4] sm:px-4 lg:px-8">선택한 유입의 세부 데이터가 없습니다.</p>
          )}
        </div>

        <div className="min-w-0 lg:border-l lg:border-[#edf1f6]">
          <div className="border-b border-[#edf1f6] px-3 py-3 sm:px-4 lg:px-6">
            <h3 className="text-[14px] font-semibold tracking-[-0.03em] text-[#16233c]">{breakdownHeading}</h3>
          </div>
          {drilldown.breakdown.length > 0 ? (
            drilldown.breakdown.map((row, index) => (
              <div key={`${row.label}-${index}`} className="flex items-center justify-between gap-3 border-b border-[#edf1f6] px-3 py-3 text-[13px] last:border-b-0 sm:px-4 lg:px-6">
                <span className="min-w-0 truncate font-medium text-[#30425f]" title={row.label}>{row.label}</span>
                <span className="shrink-0 font-semibold text-[#2f6df6]">{row.visitors.toLocaleString("ko-KR")}명</span>
              </div>
            ))
          ) : (
            <p className="px-3 py-8 text-[13px] text-[#7284a4] sm:px-4 lg:px-6">분석 가능한 세부 유입이 없습니다.</p>
          )}
        </div>
      </div>

      <div className="grid border-t border-[#edf1f6] sm:grid-cols-2">
        <section className="min-w-0">
          <div className="border-b border-[#edf1f6] px-3 py-3 sm:px-4 lg:px-8">
            <h3 className="text-[14px] font-semibold tracking-[-0.03em] text-[#16233c]">기기별 유입</h3>
          </div>
          {drilldown.devices.length > 0 ? drilldown.devices.map((row, index) => (
            <div key={`${row.label}-${index}`} className="flex items-center justify-between gap-3 border-b border-[#edf1f6] px-3 py-3 text-[13px] last:border-b-0 sm:px-4 lg:px-8">
              <span className="min-w-0 truncate font-medium text-[#30425f]">{row.label}</span>
              <span className="shrink-0 font-semibold text-[#2f6df6]">{row.visitors.toLocaleString("ko-KR")}명</span>
            </div>
          )) : <p className="px-3 py-6 text-[13px] text-[#7284a4] sm:px-4 lg:px-8">새로운 유입부터 기기 정보가 표시됩니다.</p>}
        </section>
        <section className="min-w-0 border-t border-[#edf1f6] sm:border-l sm:border-t-0">
          <div className="border-b border-[#edf1f6] px-3 py-3 sm:px-4 lg:px-8">
            <h3 className="text-[14px] font-semibold tracking-[-0.03em] text-[#16233c]">리퍼러 경로</h3>
          </div>
          {drilldown.referrers.length > 0 ? drilldown.referrers.map((row, index) => (
            <div key={`${row.label}-${index}`} className="flex items-center justify-between gap-3 border-b border-[#edf1f6] px-3 py-3 text-[13px] last:border-b-0 sm:px-4 lg:px-8">
              <span className="min-w-0 truncate font-medium text-[#30425f]" title={row.label}>{row.label}</span>
              <span className="shrink-0 font-semibold text-[#2f6df6]">{row.visitors.toLocaleString("ko-KR")}명</span>
            </div>
          )) : <p className="px-3 py-6 text-[13px] text-[#7284a4] sm:px-4 lg:px-8">새로운 유입부터 리퍼러 경로가 표시됩니다.</p>}
        </section>
      </div>

      <section className="border-t border-[#edf1f6]">
        <div className={`flex flex-col gap-1 border-b border-[#edf1f6] py-3 ${ADMIN_X_PADDING} sm:flex-row sm:items-center sm:justify-between`}>
          <div>
            <h3 className="text-[14px] font-semibold tracking-[-0.03em] text-[#16233c]">최근 익명 유입</h3>
            <p className="mt-1 text-[12px] text-[#7183a1]">
              공인 IP만 표시하며, 이전 내부 IP는 확인 불가로 처리합니다. 리퍼러 쿼리스트링과 메일 ID, 인증 토큰은 저장하지 않습니다.
            </p>
          </div>
          <KavenixMarketingPagination pagination={drilldown.pagination} />
        </div>
        {drilldown.recentVisits.length > 0 ? (
          <div className="overflow-x-auto">
            <table className="w-full min-w-[1060px] border-collapse text-left">
              <thead className="border-b border-[#edf1f6] text-[12px] font-semibold text-[#7c879b]">
                <tr>
                  <th className="px-3 py-2.5 sm:px-4 lg:px-8">시각</th>
                  <th className="px-3 py-2.5">랜딩</th>
                  <th className="px-3 py-2.5">유입 경로 / 리퍼러</th>
                  <th className="px-3 py-2.5">환경</th>
                  <th className="px-3 py-2.5">IP 주소</th>
                  <th className="px-3 py-2.5">언어·시간대</th>
                  <th className="px-3 py-2.5 sm:px-4 lg:px-8">화면</th>
                </tr>
              </thead>
              <tbody>
                {drilldown.recentVisits.map((visit, index) => (
                  <tr key={`${visit.occurredAt ?? "unknown"}-${visit.landingPath}-${index}`} className="border-b border-[#edf1f6] text-[13px] text-[#33445f] last:border-b-0">
                    <td className="whitespace-nowrap px-3 py-3 text-[#7183a1] sm:px-4 lg:px-8">{formatDateTime(visit.occurredAt)}</td>
                    <td className="max-w-[190px] truncate px-3 py-3 font-medium" title={visit.landingPath}>{visit.landingPath}</td>
                    <td className="max-w-[260px] px-3 py-3">
                      <p className="truncate font-medium" title={visit.channel}>{visit.channel}</p>
                      <p className="mt-0.5 truncate text-[11px] text-[#7d8da8]" title={visit.referrer ?? "리퍼러 미전달"}>{visit.referrer ?? "리퍼러 미전달"}</p>
                    </td>
                    <td className="whitespace-nowrap px-3 py-3">{[visit.device, visit.browser, visit.operatingSystem].filter(Boolean).join(" · ") || "알 수 없음"}</td>
                    <td className="whitespace-nowrap px-3 py-3">
                      {visit.ipAddress ? (
                        <span title={visit.ipAddressApproximate ? "이전 수집분은 네트워크 대역만 보관되어 있습니다." : undefined}>
                          {[visit.ipAddress, visit.ipAddressApproximate ? "이전 대역" : null, visit.country].filter(Boolean).join(" · ")}
                        </span>
                      ) : "확인 불가"}
                    </td>
                    <td className="whitespace-nowrap px-3 py-3">{[visit.language, visit.timezone].filter(Boolean).join(" · ") || "미수집"}</td>
                    <td className="whitespace-nowrap px-3 py-3 sm:px-4 lg:px-8">{visit.viewport ?? "미수집"}</td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
        ) : (
          <p className={`py-8 text-[13px] text-[#7284a4] ${ADMIN_X_PADDING}`}>
            새로운 유입부터 익명 환경 데이터가 표시됩니다.
          </p>
        )}
      </section>
    </section>
  );
}

function MarketingAnalyticsDashboard({ analytics }: { analytics: KavenixMarketingAnalytics }) {
  return (
    <>
      <MarketingFunnelRail analytics={analytics} />
      <MarketingProductFunnel analytics={analytics} />
      {analytics.drilldown ? <MarketingDrilldownPanel drilldown={analytics.drilldown} rangeDays={analytics.rangeDays} /> : null}
      <section className="border-b border-[#edf1f6] bg-white">
        <div className="flex flex-col gap-2 px-3 pb-3 pt-4 sm:px-4 lg:flex-row lg:items-center lg:justify-between lg:px-8">
          <div>
            <h2 className="text-[14px] font-semibold tracking-[-0.03em] text-[#16233c]">일별 유입</h2>
            <p className="mt-1 text-[12px] text-[#70819d]">
              방문자 ID 기준으로 중복을 제외한 일별 공개 페이지 유입입니다.
            </p>
          </div>
          {analytics.trackingStartedAt ? (
            <p className="text-[12px] text-[#8a98b0]">
              측정 시작 {formatDateTime(analytics.trackingStartedAt)}
            </p>
          ) : null}
        </div>
        <div className="overflow-x-auto">
          <MarketingTrend analytics={analytics} />
        </div>
      </section>
      <section className="grid bg-white lg:grid-cols-2">
        <MarketingTrafficList
          dimension="page"
          heading="상위 랜딩 페이지"
          rangeDays={analytics.rangeDays}
          rows={analytics.landingPages.map((row) => ({
            path: row.path,
            visitors: row.visitors,
          }))}
        />
        <div className="border-t border-[#edf1f6] lg:border-l lg:border-t-0">
          <MarketingTrafficList
            dimension="channel"
            heading="유입 경로"
            rangeDays={analytics.rangeDays}
            rows={analytics.channels.map((row) => ({
              label: row.label,
              visitors: row.visitors,
            }))}
          />
        </div>
      </section>
      <details className="border-t border-[#edf1f6] bg-white">
        <summary className="cursor-pointer px-3 py-4 text-[13px] font-semibold text-[#344767] sm:px-4 lg:px-8">메일함 및 설정 페이지 이용 보기</summary>
        <p className="px-3 pb-3 text-[12px] text-[#70819d] sm:px-4 lg:px-8">로그인 후 이용한 화면입니다. 공개 페이지의 유입 방문자 수에는 합산하지 않습니다. 페이지를 누르면 상세 기록을 확인할 수 있습니다.</p>
        <MarketingTrafficList dimension="page" heading="서비스 내 방문 페이지" rangeDays={analytics.rangeDays} rows={analytics.appPages.map((row) => ({ path: row.path, visitors: row.visitors }))} />
      </details>
    </>
  );
}

function UsersTable({ query, rows }: { query: string; rows: KavenixAdminUserRow[] }) {
  if (rows.length === 0) {
    return (
      <div className="border-t border-[#edf2fb] px-0 py-8 text-[14px] leading-7 text-[#7284a4]">
        {query ? "검색 조건에 맞는 사용자가 없습니다." : "아직 등록된 사용자가 없습니다."}
      </div>
    );
  }

  return (
    <div className="overflow-x-auto">
      <table className="min-w-[1200px] w-full border-collapse">
        <thead>
          <tr className="border-b border-[#edf1f6] text-left text-[12px] font-semibold text-[#7c879b]">
            <th className={`${ADMIN_CELL_START} py-2.5`}>사용자</th>
            <th className="px-4 py-2.5">대표 도메인</th>
            <th className="px-4 py-2.5">메일 계정</th>
            <th className="px-4 py-2.5">운영 수량</th>
            <th className="px-4 py-2.5">결제 상태</th>
            <th className={`pl-4 py-2.5 ${ADMIN_CELL_END}`}>최근 청구</th>
          </tr>
        </thead>
        <tbody>
          {rows.map((row) => {
            if (row.accountDeletedAt) {
              return (
                <tr
                  key={row.id}
                  className="border-b border-[#edf1f6] text-[13px] text-[#66758e] last:border-b-0"
                >
                  <td colSpan={6} className={`${ADMIN_CELL_START} ${ADMIN_CELL_END} py-4`}>
                    <div className="flex flex-wrap items-center gap-2">
                      <span className={`om-badge om-badge-sm ${badgeClass("slate")}`}>삭제됨</span>
                      <span className="text-[12px] text-[#8a98b0]">
                        삭제 시각 {formatDateTime(row.accountDeletedAt)}
                      </span>
                    </div>
                  </td>
                </tr>
              );
            }

            const isRepresentativeOwner = row.isRepresentativeOwner;
            const isManagedMember = row.isManagedMember;
            const hasTeamContext = isRepresentativeOwner || isManagedMember;
            const domainMeta = domainStatusMeta(row.latestDomainStatus);
            const mailboxMeta = mailboxStatusMeta(row.latestMailboxStatus);
            const billingMeta = billingStatusMeta(row.subscriptionStatus);
            const chargeMeta = chargeStatusMeta(row.lastChargeStatus);

            return (
              <tr
                key={row.id}
                className="border-b border-[#edf1f6] align-top text-[13px] text-[#31415f] transition-colors hover:bg-[#fafcff] last:border-b-0"
              >
                <td className={`${ADMIN_CELL_START} py-3.5`}>
                  <div className="flex flex-wrap items-center gap-1.5">
                    <p className="text-[14px] font-semibold tracking-[-0.03em] text-[#16233c]">
                      {row.companyName || row.displayName || row.email}
                    </p>
                    <span className={`om-badge om-badge-sm ${badgeClass(isManagedMember ? "slate" : "blue")}`}>
                      {isManagedMember ? "멤버 계정" : isRepresentativeOwner ? "대표 계정" : "일반 계정"}
                    </span>
                  </div>
                  <p className="mt-1 text-[12px] text-[#70819d]">{row.displayName || "-"}</p>
                  <p className="mt-1 break-all text-[12px] text-[#4d6186]">
                    {row.recoveryEmail ?? "보조 이메일 없음"}
                  </p>
                  <KavenixUserAuthActivityDialog
                    companyName={row.companyName}
                    displayName={row.displayName}
                    loginEmail={row.email}
                    recoveryEmail={row.recoveryEmail}
                    userId={row.id}
                  />
                </td>
                <td className="px-4 py-3.5">
                  {row.latestDomain ? (
                    <div className="flex flex-col gap-1.5">
                      <a
                        href={`https://${row.latestDomain}`}
                        target="_blank"
                        rel="noreferrer"
                        className="w-fit text-[14px] font-semibold text-[#2f6df6] hover:text-[#245de3]"
                      >
                        {row.latestDomain}
                      </a>
                      <span className={`om-badge om-badge-sm w-fit ${badgeClass(domainMeta.tone)}`}>
                        {domainMeta.label}
                      </span>
                      <p className="text-[12px] text-[#70819d]">최근 점검 {formatDateTime(row.latestDomainVerifiedAt)}</p>
                    </div>
                  ) : (
                    <span className="text-[13px] text-[#8a98b0]">-</span>
                  )}
                </td>
                <td className="px-4 py-3.5">
                  {row.latestMailboxEmail ? (
                    <div className="flex flex-col gap-1.5">
                      <p className="break-all text-[13px] font-medium text-[#30425f]">
                        {row.latestMailboxEmail ?? "-"}
                      </p>
                      <span className={`om-badge om-badge-sm w-fit ${badgeClass(mailboxMeta.tone)}`}>
                        {mailboxMeta.label}
                      </span>
                    </div>
                  ) : (
                    <span className="text-[13px] text-[#8a98b0]">-</span>
                  )}
                </td>
                <td className="px-4 py-3.5">
                  {isRepresentativeOwner ? (
                    <div className="space-y-1.5">
                      <p className="text-[13px] font-medium text-[#30425f]">
                        도메인 {row.domainCount.toLocaleString("ko-KR")}개
                      </p>
                      <p className="text-[13px] font-medium text-[#30425f]">
                        팀 인원 {row.activeMemberCount.toLocaleString("ko-KR")}명
                      </p>
                      <p className="text-[12px] text-[#70819d]">월 예상 {formatCurrency(row.estimatedMonthlyRevenue)}</p>
                    </div>
                  ) : isManagedMember ? (
                    <div className="space-y-1.5">
                      <p className="text-[13px] font-medium text-[#30425f]">
                        소속 팀 {row.activeMemberCount.toLocaleString("ko-KR")}명
                      </p>
                      <p className="break-all text-[12px] text-[#70819d]">
                        대표 계정 {row.billingOwnerEmail ?? "-"}
                      </p>
                      <p className="text-[12px] text-[#70819d]">팀 월 예상 {formatCurrency(row.estimatedMonthlyRevenue)}</p>
                    </div>
                  ) : (
                    <span className="text-[13px] text-[#8a98b0]">-</span>
                  )}
                </td>
                <td className="px-4 py-3.5">
                  {hasTeamContext ? (
                    <div className="flex flex-col gap-1.5">
                      <span className={`om-badge om-badge-sm w-fit ${badgeClass(billingMeta.tone)}`}>
                        {billingMeta.label}
                      </span>
                      <p className="text-[12px] text-[#70819d]">프로필 {row.billingProfileStatus ?? "-"}</p>
                      <p className="text-[12px] text-[#70819d]">다음 청구 {formatDateTime(row.nextChargeAt)}</p>
                    </div>
                  ) : (
                    <span className="text-[13px] text-[#8a98b0]">-</span>
                  )}
                </td>
                <td className={`pl-4 py-3.5 ${ADMIN_CELL_END}`}>
                  {hasTeamContext ? (
                    <div className="flex flex-col gap-1.5">
                      <span className={`om-badge om-badge-sm w-fit ${badgeClass(chargeMeta.tone)}`}>
                        {chargeMeta.label}
                      </span>
                      <p className="text-[12px] text-[#70819d]">최근 시각 {formatDateTime(row.lastChargeAt)}</p>
                    </div>
                  ) : (
                    <span className="text-[13px] text-[#8a98b0]">-</span>
                  )}
                </td>
              </tr>
            );
          })}
        </tbody>
      </table>
    </div>
  );
}

function DomainsTable({
  query,
  rows,
  sendingServers,
}: {
  query: string;
  rows: KavenixAdminDomainRow[];
  sendingServers: Array<{
    enabled: boolean;
    host: string;
    isDefault: boolean;
    key: string;
    label: string;
    port: number;
  }>;
}) {
  if (rows.length === 0) {
    return (
      <div className="border-t border-[#edf2fb] px-0 py-8 text-[14px] leading-7 text-[#7284a4]">
        {query ? "검색 조건에 맞는 도메인이 없습니다." : "아직 연결된 도메인이 없습니다."}
      </div>
    );
  }

  const attentionCount = rows.filter(
    (row) =>
      row.provisioningStatus !== "ready" &&
      row.provisioningStatus !== "cleaned",
  ).length;
  const repairEligibleCount = rows.filter((row) => row.repairEligible).length;
  const invalidDomainCount = rows.filter(
    (row) =>
      !row.domainInputValid &&
      row.provisioningStatus !== "ready" &&
      row.provisioningStatus !== "cleaned",
  ).length;

  return (
    <>
      <div
        className={`flex flex-col gap-3 border-t px-4 py-4 sm:flex-row sm:items-center sm:justify-between ${
          attentionCount > 0
            ? "border-[#f0d6da] bg-[#fff8f9]"
            : "border-[#dce7f8] bg-[#f7faff]"
        }`}
      >
        <div>
          <p className={`text-[13px] font-semibold ${attentionCount > 0 ? "text-[#a63b50]" : "text-[#284b86]"}`}>
            {attentionCount > 0
              ? `메일 서버 또는 연결 상태 이상 ${attentionCount}건`
              : "메일 연결 오류 감시 중"}
          </p>
          <p className="mt-1 text-[12px] leading-5 text-[#6f809d]">
            정상 도메인 중 누락된 대표 메일함 또는 DB 상태 {repairEligibleCount}건은 DNS 완료 여부와 관계없이 일괄 복구할 수 있습니다.
            {invalidDomainCount > 0 ? ` 도메인 형식 오류 ${invalidDomainCount}건은 자동 복구에서 제외됩니다.` : ""}
          </p>
        </div>
        <KavenixDomainRepairAllButton issueCount={repairEligibleCount} />
      </div>
      <div className="overflow-x-auto">
      <table className="w-full min-w-[1420px] table-fixed border-collapse">
        <colgroup>
          <col className="w-[14%]" />
          <col className="w-[15%]" />
          <col className="w-[13%]" />
          <col className="w-[16%]" />
          <col className="w-[8%]" />
          <col className="w-[11%]" />
          <col className="w-[9%]" />
          <col className="w-[14%]" />
        </colgroup>
        <thead>
          <tr className="border-b border-[#edf1f6] text-left text-[12px] font-semibold text-[#7c879b]">
            <th className={`${ADMIN_CELL_START} py-2.5`}>도메인</th>
            <th className="px-4 py-2.5">소유자</th>
            <th className="px-4 py-2.5">대표 메일</th>
            <th className="px-4 py-2.5">발송 서버</th>
            <th className="px-4 py-2.5">팀 인원</th>
            <th className="px-4 py-2.5">결제 상태</th>
            <th className="px-4 py-2.5">최근 청구</th>
            <th className={`pl-4 py-2.5 text-right ${ADMIN_CELL_END}`}>관리</th>
          </tr>
        </thead>
        <tbody>
          {rows.map((row) => {
            const domainMeta = domainStatusMeta(row.domainStatus);
            const mailboxMeta = mailboxStatusMeta(row.mailboxStatus);
            const provisioningMeta = provisioningStatusMeta(row.provisioningStatus);
            const billingMeta = billingStatusMeta(row.subscriptionStatus);
            const chargeMeta = chargeStatusMeta(row.lastChargeStatus);

            return (
              <tr
                key={row.id}
                className="border-b border-[#edf1f6] align-top text-[13px] text-[#31415f] transition-colors hover:bg-[#fafcff] last:border-b-0"
              >
                <td className={`${ADMIN_CELL_START} py-3.5`}>
                  <div className="flex min-w-0 items-start gap-1.5">
                    <p className="break-all text-[14px] font-semibold tracking-[-0.03em] text-[#16233c]">{row.displayDomain}</p>
                    <KavenixDomainDnsPopover
                      domain={row.displayDomain}
                      domainId={row.id}
                      dkimEnabled={row.dkimEnabled}
                      domainStatus={row.domainStatus}
                      lastCheckedAt={row.lastDnsCheckedAt ?? row.verifiedAt}
                      records={row.dnsRecords}
                    />
                  </div>
                  <div className="mt-1.5 flex flex-wrap gap-1.5">
                    <span className={`om-badge om-badge-sm ${badgeClass(domainMeta.tone)}`}>
                      {domainMeta.label}
                    </span>
                    <span className={`om-badge om-badge-sm ${badgeClass(mailboxMeta.tone)}`}>
                      {mailboxMeta.label}
                    </span>
                    {row.provisioningStatus !== "cleaned" ? (
                      <span className={`om-badge om-badge-sm ${badgeClass(provisioningMeta.tone)}`}>
                        {provisioningMeta.label}
                      </span>
                    ) : null}
                    {row.mailcowCleanupAt ? (
                      <span className="om-badge om-badge-sm border-[#f2d7d8] bg-[#fff6f6] text-[#c6535a]">
                        정리됨
                      </span>
                    ) : null}
                  </div>
                  {row.provisioningStatus !== "ready" && row.provisioningStatus !== "cleaned" ? (
                    <p className="mt-1.5 text-[11px] font-semibold text-[#b34256]">
                      {!row.domainInputValid
                        ? "도메인 형식 오류 · 자동 복구 제외"
                        : row.repairEligible
                          ? row.dnsReady
                            ? "DNS 정상 · 최고관리자 복구 필요"
                            : "DNS 대기 중 · 대표 메일함 복구 가능"
                        : row.dnsReady
                          ? "DNS 정상 · 수동 점검 필요"
                          : "DNS 미완료 · 메일 서버 상태도 점검 필요"}
                    </p>
                  ) : null}
                  <p className="mt-1.5 text-[12px] text-[#70819d]">최근 점검 {formatDateTime(row.lastDnsCheckedAt ?? row.verifiedAt)}</p>
                </td>
                <td className="px-4 py-3.5">
                  <div className="space-y-1.5">
                    <p className="break-all text-[14px] font-semibold text-[#16233c]">
                      {row.companyName || row.displayName || row.ownerEmail}
                    </p>
                    <p className="text-[12px] text-[#70819d]">{row.displayName || "-"}</p>
                    <Link
                      href={buildAdminHref({ view: "users", domain: row.displayDomain })}
                      className="break-all text-[12px] text-[#2f6df6] hover:text-[#245de3]"
                    >
                      {row.ownerEmail}
                    </Link>
                  </div>
                </td>
                <td className="px-4 py-3.5">
                  <p className="break-all text-[13px] font-medium text-[#30425f]">{row.mailboxEmail ?? "-"}</p>
                </td>
                <td className="px-4 py-3.5">
                  <KavenixDomainSendingServerSelect
                    cleanedAt={row.mailcowCleanupAt}
                    domain={row.displayDomain}
                    domainId={row.id}
                    initialServerKey={row.sendingServerKey}
                    servers={sendingServers}
                  />
                </td>
                <td className="px-4 py-3.5">
                  <p className="text-[14px] font-semibold text-[#16233c]">{row.activeMemberCount.toLocaleString("ko-KR")}명</p>
                  <p className="mt-1.5 text-[12px] text-[#70819d]">월 예상 {formatCurrency(row.expectedMonthlyRevenue)}</p>
                </td>
                <td className="px-4 py-3.5">
                  <div className="flex flex-col gap-1.5">
                    <span className={`om-badge om-badge-sm w-fit ${badgeClass(billingMeta.tone)}`}>
                      {billingMeta.label}
                    </span>
                    <p className="text-[12px] text-[#70819d]">프로필 {row.billingProfileStatus ?? "-"}</p>
                    <p className="text-[12px] text-[#70819d]">다음 청구 {formatDateTime(row.nextChargeAt)}</p>
                  </div>
                </td>
                <td className="px-4 py-3.5">
                  <div className="flex flex-col gap-1.5">
                    <span className={`om-badge om-badge-sm w-fit ${badgeClass(chargeMeta.tone)}`}>
                      {chargeMeta.label}
                    </span>
                    <p className="text-[12px] text-[#70819d]">최근 시각 {formatDateTime(row.lastChargeAt)}</p>
                  </div>
                </td>
                <td className={`pl-4 py-3.5 text-right ${ADMIN_CELL_END}`}>
                  <div className="flex flex-col items-end gap-2.5">
                    {row.repairEligible ? (
                      <KavenixDomainRepairButton
                        domain={row.displayDomain}
                        domainId={row.id}
                      />
                    ) : null}
                    <KavenixDomainOperationalBenefitToggle
                      cleanedAt={row.mailcowCleanupAt}
                      domain={row.displayDomain}
                      domainId={row.id}
                      enabled={row.operationalBenefitEnabled}
                    />
                    <div className="flex flex-wrap items-center justify-end gap-2">
                      <KavenixPrimaryEmailChangeButton
                        cleanedAt={row.mailcowCleanupAt}
                        domain={row.displayDomain}
                        domainId={row.id}
                        mailboxEmail={row.mailboxEmail}
                      />
                      <KavenixDomainCleanupButton
                        cleanedAt={row.mailcowCleanupAt}
                        domain={row.displayDomain}
                        domainId={row.id}
                      />
                    </div>
                  </div>
                </td>
              </tr>
            );
          })}
        </tbody>
      </table>
      </div>
    </>
  );
}

function MailboxesTable({
  query,
  rows,
  selectedDomain,
}: {
  query: string;
  rows: KavenixAdminMailboxRow[];
  selectedDomain: string;
}) {
  if (rows.length === 0) {
    return (
      <div className="border-t border-[#edf2fb] px-0 py-8 text-[14px] leading-7 text-[#7284a4]">
        {selectedDomain
          ? `${selectedDomain}에 등록된 메일함이 없습니다.`
          : query
            ? "검색 조건에 맞는 메일함이 없습니다."
            : "아직 등록된 메일함이 없습니다."}
      </div>
    );
  }

  return (
    <div className="overflow-x-auto">
      <table className="w-full min-w-[980px] table-fixed border-collapse">
        <colgroup>
          <col className="w-[27%]" />
          <col className="w-[18%]" />
          <col className="w-[11%]" />
          <col className="w-[15%]" />
          <col className="w-[14%]" />
          <col className="w-[15%]" />
        </colgroup>
        <thead>
          <tr className="border-b border-[#edf1f6] text-left text-[12px] font-semibold text-[#7c879b]">
            <th className={`${ADMIN_CELL_START} py-2.5`}>메일함</th>
            <th className="px-4 py-2.5">도메인</th>
            <th className="px-4 py-2.5">구분</th>
            <th className="px-4 py-2.5">메일 현황</th>
            <th className="px-4 py-2.5">최근 동기화</th>
            <th className={`pl-4 py-2.5 ${ADMIN_CELL_END}`}>상태</th>
          </tr>
        </thead>
        <tbody>
          {rows.map((row) => {
            const mailboxMeta = mailboxStatusMeta(row.status);
            const domainMeta = domainStatusMeta(row.domainStatus);
            const roleLabel = row.isRepresentative ? "대표 계정" : "멤버";
            const roleClass = row.isRepresentative
              ? "border-[#d8e4ff] bg-[#f5f8ff] text-[#2f6df6]"
              : "border-[#e3e9f2] bg-[#f8fafc] text-[#5d6f8b]";

            return (
              <tr
                key={row.id}
                className="border-b border-[#edf1f6] align-top text-[13px] text-[#31415f] transition-colors hover:bg-[#fafcff] last:border-b-0"
              >
                <td className={`${ADMIN_CELL_START} py-3.5`}>
                  <p className="break-all text-[14px] font-semibold tracking-[-0.03em] text-[#16233c]">{row.email}</p>
                  <p className="mt-1 text-[12px] text-[#70819d]">{row.displayName || "-"}</p>
                  {row.accountEmail !== row.email ? (
                    <p className="mt-1 break-all text-[12px] text-[#8a9ab5]">로그인 {row.accountEmail}</p>
                  ) : null}
                </td>
                <td className="px-4 py-3.5">
                  <Link
                    href={buildAdminHref({ view: "mailboxes", domain: row.domain })}
                    className="break-all text-[13px] font-semibold text-[#2f6df6] hover:text-[#245de3]"
                  >
                    {row.domain}
                  </Link>
                  <p className="mt-1.5 break-all text-[12px] text-[#70819d]">소유자 {row.ownerEmail}</p>
                </td>
                <td className="px-4 py-3.5">
                  <span className={`om-badge om-badge-sm ${roleClass}`}>{roleLabel}</span>
                </td>
                <td className="px-4 py-3.5">
                  <p className="text-[14px] font-semibold tracking-[-0.03em] text-[#16233c]">
                    {row.inboxTotal.toLocaleString("ko-KR")}통
                  </p>
                  <p className={`mt-1.5 text-[12px] ${row.inboxUnread > 0 ? "font-semibold text-[#2f6df6]" : "text-[#70819d]"}`}>
                    안읽음 {row.inboxUnread.toLocaleString("ko-KR")}통
                  </p>
                </td>
                <td className="px-4 py-3.5">
                  <p className="text-[12px] leading-5 text-[#5d7195]">{formatDateTime(row.lastSyncAt)}</p>
                  {row.lastSyncError ? (
                    <p className="mt-1 max-w-[180px] truncate text-[12px] text-[#c6535a]" title={row.lastSyncError}>
                      동기화 오류
                    </p>
                  ) : null}
                  {row.contentSyncErrorCount > 0 ? (
                    <p className="mt-1 text-[12px] text-[#c6535a]">
                      본문·첨부 오류 {row.contentSyncErrorCount.toLocaleString("ko-KR")}개 폴더
                    </p>
                  ) : null}
                </td>
                <td className={`pl-4 py-3.5 ${ADMIN_CELL_END}`}>
                  <div className="flex flex-wrap gap-1.5">
                    <span className={`om-badge om-badge-sm ${badgeClass(mailboxMeta.tone)}`}>{mailboxMeta.label}</span>
                    <span className={`om-badge om-badge-sm ${badgeClass(domainMeta.tone)}`}>{domainMeta.label}</span>
                    {row.managedMemberStatus === "disabled" ? (
                      <span className="om-badge om-badge-sm border-[#f2d7d8] bg-[#fff6f6] text-[#c6535a]">멤버 중지</span>
                    ) : null}
                  </div>
                  <p className="mt-1.5 text-[12px] text-[#70819d]">등록 {formatDateTime(row.createdAt)}</p>
                  <div className="mt-2.5 flex flex-wrap items-start gap-1.5">
                    <Link
                      href={buildAdminMailboxHref(row.id)}
                      className="inline-flex h-8 items-center rounded-[9px] border border-[#d5e2f8] bg-white px-3 text-[12px] font-semibold text-[#2f6df6] transition-colors hover:border-[#bfd3f7] hover:bg-[#f7faff]"
                    >
                      메일함 열기
                    </Link>
                    <KavenixMailboxSyncButton mailboxId={row.id} />
                  </div>
                </td>
              </tr>
            );
          })}
        </tbody>
      </table>
    </div>
  );
}

function AdminMailboxViewer({
  data,
  mailbox,
}: {
  data: MailAppOverview | null;
  mailbox: KavenixAdminMailboxRow;
}) {
  const folders = data?.folders ?? [];
  const messages = data?.messages ?? [];
  const selectedMessage = data?.selectedMessage ?? null;
  const currentFolder = data?.currentFolder ?? "inbox";
  const currentPage = data?.currentPage ?? 1;
  const totalPages = data?.totalPages ?? 1;
  const totalMessages = data?.totalMessages ?? messages.length;
  const visibleAttachments =
    selectedMessage?.attachments.filter((attachment) => !attachment.isInline) ?? [];
  const bodyHtmlDisplay = selectedMessage?.bodyHtmlDisplay
    ? rewriteAdminMailboxAttachmentSources(
        selectedMessage.bodyHtmlDisplay,
        mailbox.id,
      )
    : null;

  return (
    <div className="bg-white">
      <div className={`border-b border-[#edf1f6] py-3 ${ADMIN_X_PADDING}`}>
        <Link
          href={buildAdminHref({
            domain: mailbox.domain,
            view: "mailboxes",
          })}
          className="inline-flex h-9 items-center gap-1.5 rounded-[9px] px-1 text-[13px] font-semibold text-[#526784] transition-colors hover:text-[#2f6df6]"
        >
          <ArrowLeftIcon className="h-[16px] w-[16px]" />
          <span>메일 관리로 돌아가기</span>
        </Link>
      </div>

      <div className={`border-b border-[#edf1f6] py-4 ${ADMIN_X_PADDING}`}>
        <div className="flex flex-col gap-3 sm:flex-row sm:items-start sm:justify-between">
          <div className="min-w-0">
            <div className="flex flex-wrap items-center gap-2">
              <h2 className="break-all text-[18px] font-semibold tracking-[-0.04em] text-[#16233c]">
                {mailbox.email}
              </h2>
              <span className="om-badge om-badge-sm om-badge-info">읽기 전용</span>
            </div>
            <p className="mt-1.5 text-[12px] leading-5 text-[#70819d]">
              {mailbox.displayName} · {mailbox.domain} · {mailbox.isRepresentative ? "대표 계정" : "멤버"}
            </p>
          </div>
          <div className="shrink-0 rounded-[10px] border border-[#d8e5f8] bg-[#f7faff] px-3 py-2 text-[12px] font-medium leading-5 text-[#526784]">
            관리자 조회는 고객 메일의 읽음 상태를 변경하지 않습니다.
          </div>
        </div>
      </div>

      <div className={`border-b border-[#edf1f6] py-3 ${ADMIN_X_PADDING}`}>
        <div className="flex gap-1.5 overflow-x-auto pb-0.5">
          {folders.map((folder) => {
            const active = folder.systemName === currentFolder;
            return (
              <Link
                key={folder.id}
                href={buildAdminMailboxHref(mailbox.id, {
                  folder: folder.systemName,
                })}
                className={`inline-flex h-9 shrink-0 items-center gap-1.5 rounded-[9px] px-3 text-[13px] font-semibold transition-colors ${
                  active
                    ? "bg-[#edf4ff] text-[#2f6df6]"
                    : "text-[#667792] hover:bg-[#f7faff] hover:text-[#2f6df6]"
                }`}
              >
                <span>{adminMailboxFolderLabel(folder.systemName)}</span>
                <span className={active ? "text-[#2f6df6]" : "text-[#9aa7bb]"}>
                  {folder.unreadCount || folder.count}
                </span>
              </Link>
            );
          })}
        </div>
      </div>

      {!data ? (
        <div className={`${ADMIN_X_PADDING} py-14 text-center text-[14px] leading-7 text-[#7b8ca8]`}>
          이 메일함 데이터를 불러오지 못했습니다.
        </div>
      ) : (
        <div className="grid min-h-[620px] xl:grid-cols-[minmax(340px,0.82fr)_minmax(0,1.48fr)]">
          <div
            className={`min-w-0 border-b border-[#edf1f6] xl:block xl:border-b-0 xl:border-r ${
              selectedMessage ? "hidden" : "block"
            }`}
          >
            <div className={`flex items-center justify-between border-b border-[#edf1f6] py-3 ${ADMIN_X_PADDING}`}>
              <div className="flex items-center gap-2 text-[14px]">
                <span className="font-semibold text-[#16233c]">
                  {adminMailboxFolderLabel(currentFolder)}
                </span>
                <span className="font-semibold text-[#2f6df6]">{totalMessages.toLocaleString("ko-KR")}</span>
              </div>
              <span className="text-[12px] text-[#7b8ca8]">
                {currentPage} / {totalPages}
              </span>
            </div>

            <div className="divide-y divide-[#edf1f6]">
              {messages.length === 0 ? (
                <div className="px-4 py-12 text-center text-[13px] leading-6 text-[#7b8ca8]">
                  표시할 메일이 없습니다.
                </div>
              ) : (
                messages.map((message) => {
                  const active = selectedMessage?.id === message.id;
                  return (
                    <Link
                      key={message.id}
                      href={buildAdminMailboxHref(mailbox.id, {
                        folder: currentFolder,
                        messageId: message.id,
                        page: currentPage,
                      })}
                      className={`block px-3 py-3 transition-colors sm:px-4 lg:px-8 ${
                        active ? "bg-[#f4f8ff]" : "hover:bg-[#fafcff]"
                      }`}
                    >
                      <div className="flex items-start justify-between gap-3">
                        <p
                          className={`min-w-0 truncate text-[14px] ${
                            message.isRead
                              ? "font-medium text-[#33445f]"
                              : "font-semibold text-[#17233c]"
                          }`}
                        >
                          {adminMailboxSenderLabel(message)}
                        </p>
                        <span className="shrink-0 text-[12px] text-[#8b98aa]">
                          {formatDateTime(message.receivedAt)}
                        </span>
                      </div>
                      <p
                        className={`mt-1 truncate text-[13px] ${
                          message.isRead
                            ? "text-[#4f5f78]"
                            : "font-semibold text-[#1f2c45]"
                        }`}
                      >
                        {message.subject || "(제목 없음)"}
                      </p>
                      <p className="mt-1 line-clamp-2 text-[12px] leading-5 text-[#7b8ca8]">
                        {message.snippet || "미리보기 내용이 없습니다."}
                      </p>
                    </Link>
                  );
                })
              )}
            </div>

            {totalPages > 1 ? (
              <div className={`flex items-center justify-between border-t border-[#edf1f6] py-3 ${ADMIN_X_PADDING}`}>
                <Link
                  href={buildAdminMailboxHref(mailbox.id, {
                    folder: currentFolder,
                    page: Math.max(1, currentPage - 1),
                  })}
                  aria-disabled={currentPage <= 1}
                  className={`text-[13px] font-semibold ${
                    currentPage <= 1
                      ? "pointer-events-none text-[#b5bfce]"
                      : "text-[#526784] hover:text-[#2f6df6]"
                  }`}
                >
                  이전
                </Link>
                <Link
                  href={buildAdminMailboxHref(mailbox.id, {
                    folder: currentFolder,
                    page: Math.min(totalPages, currentPage + 1),
                  })}
                  aria-disabled={currentPage >= totalPages}
                  className={`text-[13px] font-semibold ${
                    currentPage >= totalPages
                      ? "pointer-events-none text-[#b5bfce]"
                      : "text-[#526784] hover:text-[#2f6df6]"
                  }`}
                >
                  다음
                </Link>
              </div>
            ) : null}
          </div>

          <div className={`min-w-0 bg-white ${selectedMessage ? "block" : "hidden xl:block"}`}>
            {selectedMessage ? (
              <article className="px-3 py-5 sm:px-4 lg:px-8">
                <Link
                  href={buildAdminMailboxHref(mailbox.id, {
                    folder: currentFolder,
                    page: currentPage,
                  })}
                  className="mb-4 inline-flex h-8 items-center gap-1.5 text-[12px] font-semibold text-[#526784] transition-colors hover:text-[#2f6df6] xl:hidden"
                >
                  <ArrowLeftIcon className="h-[14px] w-[14px]" />
                  <span>메일 목록</span>
                </Link>
                <div className="border-b border-[#edf1f6] pb-4">
                  <div className="flex flex-wrap items-center gap-2">
                    <p className="text-[12px] font-semibold text-[#2f6df6]">
                      {selectedMessage.direction === "outbound" ? "보낸 메일" : "받은 메일"}
                    </p>
                    {!selectedMessage.isRead ? (
                      <span className="text-[11px] font-semibold text-[#8290a6]">고객 기준 안읽음</span>
                    ) : null}
                  </div>
                  <h2 className="mt-2 break-words text-[20px] font-semibold leading-8 tracking-[-0.045em] text-[#16233c] sm:text-[22px]">
                    {selectedMessage.subject || "(제목 없음)"}
                  </h2>
                  <div className="mt-4 grid gap-2 text-[13px] leading-5 text-[#667792]">
                    <p className="break-all">
                      보낸 사람{" "}
                      <span className="font-medium text-[#22324d]">
                        {selectedMessage.fromName
                          ? `${selectedMessage.fromName} <${selectedMessage.fromAddress}>`
                          : selectedMessage.fromAddress}
                      </span>
                    </p>
                    <p className="break-all">
                      받는 사람{" "}
                      <span className="font-medium text-[#22324d]">
                        {selectedMessage.toAddresses || "-"}
                      </span>
                    </p>
                    <p>{formatDateTime(selectedMessage.receivedAt)}</p>
                  </div>
                </div>

                {bodyHtmlDisplay ? (
                  <div
                    className="mail-content mt-5 max-w-none overflow-x-auto text-[14px] leading-7 text-[#22324d]"
                    dangerouslySetInnerHTML={{ __html: bodyHtmlDisplay }}
                  />
                ) : (
                  <pre className="mt-5 whitespace-pre-wrap break-words text-[14px] leading-7 text-[#22324d]">
                    {selectedMessage.bodyText || selectedMessage.snippet || "본문이 없습니다."}
                  </pre>
                )}

                {visibleAttachments.length > 0 ? (
                  <div className="mt-6 border-t border-[#edf1f6] pt-4">
                    <p className="text-[13px] font-semibold text-[#30425f]">
                      첨부파일 {visibleAttachments.length.toLocaleString("ko-KR")}개
                    </p>
                    <div className="mt-2 grid gap-2 sm:grid-cols-2">
                      {visibleAttachments.map((attachment) => (
                        <a
                          key={`${attachment.index}-${attachment.filename}`}
                          href={buildAdminMailboxAttachmentHref({
                            attachmentIndex: attachment.index,
                            mailboxId: mailbox.id,
                            messageId: selectedMessage.id,
                          })}
                          className="flex min-w-0 items-center justify-between gap-3 rounded-[9px] border border-[#e1e8f3] px-3 py-2.5 text-[12px] transition-colors hover:border-[#cddcf4] hover:bg-[#f8faff]"
                        >
                          <span className="min-w-0 truncate font-medium text-[#405370]">
                            {attachment.filename}
                          </span>
                          <span className="shrink-0 font-semibold text-[#2f6df6]">다운로드</span>
                        </a>
                      ))}
                    </div>
                  </div>
                ) : null}
              </article>
            ) : (
              <div className="flex min-h-[420px] items-center justify-center px-4 text-center text-[14px] leading-7 text-[#7b8ca8]">
                왼쪽 목록에서 메일을 선택하면 본문을 확인할 수 있습니다.
              </div>
            )}
          </div>
        </div>
      )}
    </div>
  );
}

function ChargesTable({ query, rows }: { query: string; rows: KavenixAdminChargeRow[] }) {
  if (rows.length === 0) {
    return (
      <div className="border-t border-[#edf2fb] px-0 py-8 text-[14px] leading-7 text-[#7284a4]">
        {query ? "검색 조건에 맞는 결제 내역이 없습니다." : "아직 저장된 결제 내역이 없습니다."}
      </div>
    );
  }

  return (
    <div className="overflow-x-auto">
      <table className="w-full min-w-[1080px] table-fixed border-collapse">
        <colgroup>
          <col className="w-[18%]" />
          <col className="w-[24%]" />
          <col className="w-[13%]" />
          <col className="w-[12%]" />
          <col className="w-[12%]" />
          <col className="w-[12%]" />
          <col className="w-[9%]" />
        </colgroup>
        <thead>
          <tr className="border-b border-[#edf1f6] text-left text-[12px] font-semibold text-[#7c879b]">
            <th className={`${ADMIN_CELL_START} py-2.5`}>사용자</th>
            <th className="px-4 py-2.5">상품 / 주문</th>
            <th className="px-4 py-2.5">결제수단</th>
            <th className="px-4 py-2.5">승인 금액</th>
            <th className="px-4 py-2.5">상태</th>
            <th className="px-4 py-2.5">승인 시각</th>
            <th className={`pl-4 py-2.5 text-right ${ADMIN_CELL_END}`}>관리</th>
          </tr>
        </thead>
        <tbody>
          {rows.map((row) => {
            const refundMeta = refundStateMeta(row.refundState);
            const latestRefund = latestRefundMeta(row.latestRefundStatus);
            const cancellationMeta = cancellationReviewMeta(row);
            const stageMeta = chargeStageMeta(row);
            const reviewPending =
              row.cancellationRequestId !== null &&
              row.cancellationReviewStatus === "pending_review" &&
              row.cancellationRequestStatus === "pending";
            const buttonLabel =
              row.refundedAmount > 0 && row.remainingRefundableAmount > 0 ? "잔액 환불" : "전액 환불";
            const primaryName = row.companyName || row.displayName || row.ownerEmail;
            const paymentLabel =
              [row.cardCompanyName, row.cardNum4Print ? `(${row.cardNum4Print})` : null]
                .filter(Boolean)
                .join(" ") || row.payMethod || "-";
            const chargeTypeLabel =
              row.provider === "polar"
                ? row.paymentTrigger === "purchase"
                  ? "최초 결제"
                  : row.paymentTrigger === "subscription_create"
                    ? "구독 시작"
                  : row.paymentTrigger === "subscription_cycle"
                    ? "정기 갱신"
                    : row.paymentTrigger === "subscription_update"
                      ? "구독 변경"
                    : row.paymentTrigger?.startsWith("retry_")
                      ? "결제 재시도"
                      : "해외 결제"
                : row.chargeKind === "cycle"
                  ? "정기 청구"
                  : "즉시 청구";

            let disabledReason = "";

            if (row.provider === "polar") {
              disabledReason = "Polar 결제의 환불과 카드 관리는 Polar 대시보드에서 처리합니다.";
            } else if (row.chargeStatus !== "success") {
              disabledReason = "성공 승인된 결제만 환불할 수 있습니다.";
            } else if (reviewPending) {
              disabledReason = "청약철회 검토 대기 중인 결제는 먼저 승인 또는 반려를 결정해 주세요.";
            } else if (!row.payTokenAvailable) {
              disabledReason = "환불 토큰이 없는 결제라서 취소를 진행할 수 없습니다.";
            } else if (row.pendingRefundCount > 0) {
              disabledReason = "이미 환불 처리 중인 요청이 있습니다.";
            } else if (row.remainingRefundableAmount <= 0) {
              disabledReason = "이미 전액 환불된 결제입니다.";
            }

            const stageBadgeClass = chargeStageBadgeClass(stageMeta.variant);
            const detailBadges = [
              { label: row.provider === "polar" ? "Polar · 해외" : "Toss · 국내", className: chargeStageBadgeClass("muted") },
              { label: stageMeta.label, className: stageBadgeClass },
            ];

            const summaryRows = [
              { label: "결제 제공자", value: row.provider === "polar" ? "Polar" : "Toss Payments" },
              { label: "주문번호", value: row.orderNo },
              { label: "상품", value: row.productDesc },
              { label: "도메인", value: row.displayDomain ?? "-" },
              { label: "대표 메일", value: row.latestMailboxEmail ?? "-" },
              { label: "소유자", value: row.ownerEmail },
              { label: "요청 시각", value: formatDateTime(row.requestedAt) },
            ];

            const paymentRows = [
              { label: "승인 금액", value: formatChargeAmount(row.amount, row.currency) },
              {
                label: row.provider === "polar" ? "통화" : "면세 금액",
                value:
                  row.provider === "polar"
                    ? row.currency.toUpperCase()
                    : formatCurrency(row.amountTaxFree),
              },
              { label: "결제수단", value: row.payMethod ?? "-" },
              { label: "카드 정보", value: paymentLabel },
              { label: "청구 방식", value: chargeTypeLabel },
              { label: "승인 시각", value: formatDateTime(row.approvedAt) },
            ];

            const refundRows =
              row.provider === "polar"
                ? []
                : [
                    { label: "환불 상태", value: refundMeta.label },
                    { label: "최근 환불 상태", value: latestRefund.label },
                    { label: "환불 완료 금액", value: formatCurrency(row.refundedAmount) },
                    { label: "남은 환불 가능액", value: formatCurrency(row.remainingRefundableAmount) },
                    { label: "최근 환불 요청", value: formatDateTime(row.latestRefundRequestedAt) },
                    { label: "최근 환불 완료", value: formatDateTime(row.latestRefundedAt) },
                    { label: "최근 요청자", value: row.latestRefundRequestedByEmail ?? "-" },
                  ];

            const withdrawalRows = row.provider === "toss" && row.cancellationRequestId
              ? [
                  { label: "요청 상태", value: cancellationMeta?.label ?? "-" },
                  { label: "요청 시각", value: formatDateTime(row.cancellationRequestedAt) },
                  { label: "요청자", value: row.cancellationRequestedByEmail ?? "-" },
                  { label: "검토자", value: row.cancellationReviewedByEmail ?? "-" },
                  { label: "검토 시각", value: formatDateTime(row.cancellationReviewedAt) },
                  {
                    label: "승인 환불액",
                    value:
                      row.cancellationApprovedRefundAmount !== null
                        ? formatCurrency(row.cancellationApprovedRefundAmount)
                        : "-",
                  },
                  { label: "처리 결과", value: formatCancellationResult(row.cancellationResultText) },
                ]
              : [];

            const notes = [
              row.errorMessage || row.errorCode
                ? {
                    label: "결제 오류",
                    text: [row.errorMessage, row.errorCode ? `코드: ${row.errorCode}` : null]
                      .filter(Boolean)
                      .join(" · "),
                    tone: "danger" as const,
                  }
                : null,
              row.latestRefundReason ? { label: "환불 사유", text: row.latestRefundReason } : null,
              row.latestRefundErrorMessage
                ? { label: "환불 오류", text: row.latestRefundErrorMessage, tone: "danger" as const }
                : null,
              row.cancellationReviewNote
                ? {
                    label: "검토 메모",
                    text: formatCancellationReviewNote(row.cancellationReviewNote) ?? row.cancellationReviewNote,
                  }
                : null,
            ].filter((note): note is NonNullable<typeof note> => note !== null);

            return (
              <tr
                key={`${row.provider}-${row.id}`}
                className="border-b border-[#edf1f6] align-top text-[13px] text-[#31415f] transition-colors hover:bg-[#fafcff] last:border-b-0"
              >
                <td className={`${ADMIN_CELL_START} py-3.5`}>
                  <p className="break-all text-[14px] font-semibold tracking-[-0.02em] text-[#16233c]">
                    {primaryName}
                  </p>
                  <p className="mt-1 break-all text-[12px] text-[#5d7195]">{row.ownerEmail}</p>
                  <p className="mt-1 text-[12px] text-[#8a9ab5]">{row.displayDomain ?? "-"}</p>
                </td>
                <td className="px-4 py-3.5">
                  <p className="break-all text-[13px] font-medium leading-5 text-[#30425f]">{row.productDesc}</p>
                  <p className="mt-1.5 break-all text-[12px] text-[#8a9ab5]">
                    {row.provider === "polar" ? "Polar" : "Toss Payments"} · {row.orderNo}
                  </p>
                </td>
                <td className="px-4 py-3.5">
                  <p className="break-words text-[13px] font-medium text-[#30425f]">{paymentLabel}</p>
                  <p className="mt-1.5 text-[12px] text-[#8a9ab5]">
                    {chargeTypeLabel}
                  </p>
                </td>
                <td className="px-4 py-3.5">
                  <p className="text-[14px] font-semibold tracking-[-0.03em] text-[#16233c]">
                    {formatChargeAmount(row.amount, row.currency)}
                  </p>
                  {row.refundedAmount > 0 ? (
                    <p className="mt-1.5 text-[12px] text-[#8a9ab5]">
                      환불 {formatChargeAmount(row.refundedAmount, row.currency)}
                    </p>
                  ) : null}
                </td>
                <td className="px-4 py-3.5">
                  <span
                    className={`om-badge om-badge-sm gap-1.5 ${stageBadgeClass}`}
                  >
                    <span className={`h-1.5 w-1.5 rounded-full ${chargeStageDotClass(stageMeta.variant)}`} />
                    {stageMeta.label}
                  </span>
                </td>
                <td className="px-4 py-3.5">
                  <p className="text-[12px] leading-5 text-[#5d7195]">
                    {formatDateTime(row.approvedAt ?? row.requestedAt)}
                  </p>
                </td>
                <td className={`pl-4 py-3.5 ${ADMIN_CELL_END}`}>
                  <div className="flex justify-end">
                    <KavenixChargeDetailsDialog
                      title={primaryName}
                      subtitle={`${row.ownerEmail} · ${row.displayDomain ?? "도메인 없음"}`}
                      badges={detailBadges}
                      summaryRows={summaryRows}
                      paymentRows={paymentRows}
                      refundRows={refundRows}
                      withdrawalRows={withdrawalRows}
                      notes={notes}
                      actionHint={
                        disabledReason ||
                        (reviewPending
                          ? "청약철회 요청 검토 후 즉시 상태가 갱신됩니다."
                          : row.latestRefundRequestedByEmail
                            ? `최근 환불 요청자: ${row.latestRefundRequestedByEmail}`
                            : null)
                      }
                      action={
                        row.provider === "polar" ? (
                          <a
                            className="om-btn-secondary inline-flex h-11 items-center justify-center rounded-[10px] px-4 text-[13px] font-semibold"
                            href="https://polar.sh/dashboard/officialmail/sales"
                            rel="noreferrer"
                            target="_blank"
                          >
                            Polar에서 관리
                          </a>
                        ) : reviewPending && row.cancellationRequestId ? (
                          <KavenixCancellationReviewActions
                            requestId={row.cancellationRequestId}
                            remainingRefundableAmount={row.remainingRefundableAmount}
                            className="grid gap-2 sm:grid-cols-3"
                          />
                        ) : (
                          <KavenixChargeRefundButton
                            chargeId={row.id}
                            disabled={!row.canRefund}
                            disabledReason={disabledReason}
                            label={buttonLabel}
                            className={`h-11 rounded-[10px] px-4 text-[13px] font-semibold ${
                              row.canRefund
                                ? "om-btn-primary"
                                : "cursor-not-allowed rounded-[10px] border border-[#d8e3f6] bg-[#f7f9fd] text-[#97a7c2]"
                            }`}
                          />
                        )
                      }
                    />
                  </div>
                </td>
              </tr>
            );
          })}
        </tbody>
      </table>
    </div>
  );
}

export default async function KavenixPage(props: PageProps<"/kavenix">) {
  const user = await requireSessionUser();

  if (!isKavenixAdminEmail(user.email)) {
    notFound();
  }

  const searchParams = await props.searchParams;
  const view =
    searchParams.view === "statistics" ||
    searchParams.view === "analytics" ||
    searchParams.view === "search" ||
    searchParams.view === "blog" ||
    searchParams.view === "domains" ||
    searchParams.view === "sending-servers" ||
    searchParams.view === "dkim-reminders" ||
    searchParams.view === "domain-assistance" ||
    searchParams.view === "promotion-codes" ||
    searchParams.view === "app-versions" ||
    searchParams.view === "mailboxes" ||
    searchParams.view === "charges"
      ? searchParams.view
      : "users";
  const query = typeof searchParams.q === "string" ? searchParams.q : "";
  const selectedDomain = typeof searchParams.domain === "string" ? searchParams.domain : "";
  const requestedMailboxId = Number(searchParams.mailbox);
  const selectedMailboxId =
    Number.isInteger(requestedMailboxId) && requestedMailboxId > 0
      ? requestedMailboxId
      : null;
  const selectedMailboxFolder =
    typeof searchParams.mailFolder === "string"
      ? searchParams.mailFolder.trim().slice(0, 80) || "inbox"
      : "inbox";
  const requestedMailboxPage = Number(searchParams.mailPage);
  const selectedMailboxPage =
    Number.isInteger(requestedMailboxPage) && requestedMailboxPage > 0
      ? requestedMailboxPage
      : 1;
  const requestedMailboxMessageId = Number(searchParams.mailMessage);
  const selectedMailboxMessageId =
    Number.isInteger(requestedMailboxMessageId) && requestedMailboxMessageId > 0
      ? requestedMailboxMessageId
      : null;
  const chargeFilter = normalizeKavenixChargeFilter(
    typeof searchParams.chargeFilter === "string" ? searchParams.chargeFilter : "",
  );
  const rangeDays = normalizeKavenixMarketingRangeDays(
    typeof searchParams.range === "string" ? searchParams.range : null,
  );
  const statisticsRange = normalizeKavenixStatisticsRange(
    typeof searchParams.statsRange === "string" ? searchParams.statsRange : null,
  );
  const marketingDrilldown = normalizeKavenixMarketingDrilldown({
    dimension: typeof searchParams.drill === "string" ? searchParams.drill : null,
    value: typeof searchParams.drillValue === "string" ? searchParams.drillValue : null,
  });
  const googleSearchConsoleStatus = typeof searchParams.gsc === "string" ? searchParams.gsc : null;
  const googleSearchConsoleRange = [7, 28, 90].includes(Number(searchParams.searchRange))
    ? Number(searchParams.searchRange)
    : 28;
  const selectedBlogPostId = typeof searchParams.postId === "string"
    ? Number(searchParams.postId)
    : null;
  const newBlogQuery = typeof searchParams.newQuery === "string"
    ? searchParams.newQuery.trim().slice(0, 160)
    : "";
  const mailEntryUrl = await getMailEntryUrlForCurrentRequest(user);
  const [
    dataset,
    statistics,
    analytics,
    marketingVisitorCount,
    googleSearchConsoleAnalytics,
    marketingBlogPostCount,
    marketingBlogPosts,
    dkimReminderRows,
    domainAssistanceCount,
    domainAssistanceRequests,
    promotionCodeCount,
    promotionCodes,
    selectedMailbox,
  ] = await Promise.all([
    getKavenixAdminDataset({
      chargeFilter,
      domain: selectedDomain,
      query,
    }),
    view === "statistics"
      ? getKavenixStatistics(statisticsRange)
      : Promise.resolve(null),
    view === "analytics"
      ? getKavenixMarketingAnalytics({ drilldown: marketingDrilldown, rangeDays, page: searchParams.visitsPage, pageSize: searchParams.visitsPageSize })
      : Promise.resolve(null),
    view === "analytics"
      ? Promise.resolve(null)
      : getKavenixMarketingVisitorCount({ rangeDays }),
    view === "search"
      ? getKavenixGoogleSearchConsoleAnalytics(googleSearchConsoleRange)
      : Promise.resolve(null),
    getKavenixMarketingBlogPostCount(),
    view === "blog"
      ? getKavenixMarketingBlogPosts()
      : Promise.resolve(null),
    getKavenixDkimReminderRows(),
    getKavenixDomainSetupAssistanceRequestCount(),
    view === "domain-assistance"
      ? getKavenixDomainSetupAssistanceRequests({
          domain: selectedDomain,
          query,
        })
      : Promise.resolve(null),
    getKavenixDomainSetupPromotionCodeCount(),
    view === "promotion-codes"
      ? getKavenixDomainSetupPromotionCodes()
      : Promise.resolve(null),
    view === "mailboxes" && selectedMailboxId
      ? getKavenixAdminMailboxById(selectedMailboxId)
      : Promise.resolve(null),
  ]);
  if (view === "mailboxes" && selectedMailboxId && !selectedMailbox) {
    notFound();
  }
  if (selectedMailbox) {
    try {
      await refreshMailboxIfStaleByEmail(selectedMailbox.accountEmail, {
        folder: selectedMailboxFolder,
        mailboxId: selectedMailbox.id,
      });
    } catch {
      // Keep admin inspection available when the remote mailbox is temporarily unavailable.
    }
  }
  const selectedMailboxData = selectedMailbox
    ? await getMailAppOverviewByEmail(selectedMailbox.accountEmail, {
        folder: selectedMailboxFolder,
        mailboxId: selectedMailbox.id,
        markMessageRead: false,
        messageId: selectedMailboxMessageId,
        page: selectedMailboxPage,
        pageSize: 20,
        sortOrder: "latest",
      })
    : null;
  const googleSearchConsoleBlogStatus =
    view === "blog" && marketingBlogPosts
      ? await getKavenixGoogleSearchConsoleBlogStatus(marketingBlogPosts)
      : null;

  const resultCount =
    view === "statistics"
      ? (statistics?.actionItems.reduce((sum, item) => sum + item.count, 0) ?? 0)
      : view === "analytics"
      ? (analytics?.metrics.landingVisitors ?? 0)
      : view === "search"
        ? (googleSearchConsoleAnalytics?.metrics.clicks ?? 0)
      : view === "blog"
        ? marketingBlogPostCount
      : view === "users"
      ? dataset.users.length
      : view === "domains"
        ? dataset.domains.length
        : view === "sending-servers"
          ? dataset.sendingServers.length
        : view === "dkim-reminders"
          ? dkimReminderRows.length
        : view === "domain-assistance"
          ? (domainAssistanceRequests?.length ?? 0)
        : view === "promotion-codes"
          ? promotionCodeCount
        : view === "app-versions"
          ? 2
        : view === "mailboxes"
          ? selectedMailboxData?.totalMessages ?? dataset.mailboxes.length
          : dataset.charges.length;
  const analyticsVisitorCount = analytics?.metrics.landingVisitors ?? marketingVisitorCount ?? 0;

  const sectionTitle =
    view === "statistics"
      ? "운영 통계"
      : view === "analytics"
      ? "유입 분석"
      : view === "search"
        ? "검색 성과"
      : view === "blog"
        ? "블로그 관리"
      : view === "users"
      ? "사용자 목록"
      : view === "domains"
        ? "도메인 목록"
        : view === "sending-servers"
          ? "발송 서버 관리"
        : view === "dkim-reminders"
          ? "DKIM 안내"
        : view === "domain-assistance"
          ? "설정 대행 신청"
        : view === "promotion-codes"
          ? "프로모션 코드"
        : view === "app-versions"
          ? "앱 버전 관리"
        : view === "mailboxes"
          ? selectedMailbox
            ? "메일함 보기"
            : "메일 관리"
          : "결제 내역";
  const sectionDescription =
    view === "statistics"
      ? "고객 전환, 실제 메일 사용, 매출, 기능 채택과 운영 장애를 한 화면에서 교차 확인합니다."
      : view === "analytics"
      ? "공개 페이지 유입부터 가입, 도메인 연결, 성장플랜 전환까지의 퍼널을 기간별로 확인합니다."
      : view === "search"
        ? "Google Search Console을 연결해 검색 유입과 개선 기회를 매일 확인합니다."
      : view === "blog"
        ? "블록을 자유롭게 배치해 가이드를 작성하고, 미리보기·임시저장·발행 상태를 한곳에서 관리합니다."
      : view === "users"
      ? "대표 도메인, 대표 메일, 활성 멤버, 자동결제 상태를 사용자 기준으로 확인합니다."
      : view === "domains"
        ? "도메인별 소유자, 대표 메일, 활성 멤버, 자동결제 상태를 도메인 기준으로 확인합니다."
        : view === "sending-servers"
          ? "기본 서버와 추가 SMTP 발송 서버를 관리하고 도메인 할당 현황을 확인합니다."
        : view === "dkim-reminders"
          ? "최초 DNS 연결 미완료와 신규 DKIM 재인증 대상을 구분해 보조 이메일로 안내합니다."
        : view === "domain-assistance"
          ? "도메인 연결 설정 대행 신청과 임시 계정정보, 처리 상태를 관리합니다."
        : view === "promotion-codes"
          ? "설정 대행 할인 코드를 발급하고 사용 기간, 횟수, 활성 상태를 관리합니다."
        : view === "app-versions"
          ? "플랫폼별 최신·최소 지원 버전과 권장·강제 업데이트를 관리합니다."
        : view === "mailboxes"
          ? selectedMailbox
            ? "고객의 읽음 상태를 변경하지 않고 메일 목록과 본문을 읽기 전용으로 확인합니다."
            : "도메인을 선택해 대표 계정과 멤버 메일함의 동기화, 받은메일 수, 사용 상태를 확인합니다."
          : "결제 상태를 빠르게 확인하고, 자세한 기록과 관리자 조치는 상세 팝업에서 처리합니다.";
  const navItems: AdminNavItem[] = [
    {
      count: statistics?.actionItems.reduce((sum, item) => sum + item.count, 0),
      description: "전환, 사용량, 매출, 운영 상태",
      label: "운영 통계",
      view: "statistics",
    },
    {
      count: analyticsVisitorCount,
      description: "유입부터 성장플랜 전환 퍼널",
      label: "유입 분석",
      view: "analytics",
    },
    {
      description: "검색 클릭, 노출, 유입 페이지",
      label: "검색 성과",
      view: "search",
    },
    {
      count: marketingBlogPostCount,
      description: "블록 편집과 공개 발행 관리",
      label: "블로그 관리",
      view: "blog",
    },
    {
      count: dataset.users.length,
      description: "계정, 대표 도메인, 결제 상태",
      label: "사용자 목록",
      view: "users",
    },
    {
      count: dataset.domains.length,
      description: "도메인 연결과 메일함 상태",
      label: "도메인 목록",
      view: "domains",
    },
    {
      count: dataset.sendingServers.length,
      description: "SMTP 연결 정보와 할당 현황",
      label: "발송 서버 관리",
      view: "sending-servers",
    },
    {
      count: dkimReminderRows.length,
      description: "DNS 미연결과 DKIM 재인증 안내",
      label: "DKIM 안내",
      view: "dkim-reminders",
    },
    {
      count: domainAssistanceCount,
      description: "DNS 연결 대행 접수와 처리",
      label: "설정 대행 신청",
      view: "domain-assistance",
    },
    {
      count: promotionCodeCount,
      description: "설정 대행 할인과 사용 한도",
      label: "프로모션 코드",
      view: "promotion-codes",
    },
    {
      description: "최신 버전, 최소 지원 버전, 구버전 차단",
      label: "앱 버전 관리",
      view: "app-versions",
    },
    {
      count: dataset.mailboxes.length,
      description: "도메인별 메일함 상태",
      label: "메일 관리",
      view: "mailboxes",
    },
    {
      count: dataset.charges.length,
      description: "결제, 환불, 청약철회",
      label: "결제 내역",
      view: "charges",
    },
  ];

  return (
    <div className="min-h-screen bg-white text-[#16233c]">
      <div className="flex min-h-screen">
        <AdminSidebar
          chargeFilter={chargeFilter}
          currentView={view}
          domain={selectedDomain}
          items={navItems}
          q={query}
          rangeDays={rangeDays}
          userEmail={user.email}
        />

        <main className="min-w-0 flex-1 bg-white">
          <section className={`border-b border-[#edf1f6] pb-3 pt-4 lg:pb-3 lg:pt-6 ${ADMIN_X_PADDING}`}>
            <div className="mb-3 lg:hidden">
              <AdminMobileMenu
                chargeFilter={chargeFilter}
                currentView={view}
                domain={selectedDomain}
                items={navItems}
                q={query}
                rangeDays={rangeDays}
              />
            </div>

            <div className="flex flex-col gap-3 lg:flex-row lg:items-start lg:justify-between">
              <div className="min-w-0">
                <div className="flex flex-wrap items-center gap-x-2 gap-y-2 text-[15px] leading-none sm:gap-x-3 sm:text-[16px]">
                  <h1 className="text-[16px] font-semibold tracking-[-0.03em] text-[#111a33] sm:text-[17px]">
                    {sectionTitle}
                  </h1>
                  <span className="font-semibold text-[#2f6df6]">{resultCount.toLocaleString("ko-KR")}</span>
                  <span className="text-[#7c879b]">{view === "analytics" ? "명" : view === "search" ? "클릭" : "건"}</span>
                </div>
                <p className="mt-2 text-[13px] leading-6 text-[#70819d]">{sectionDescription}</p>
              </div>

              <div className="flex shrink-0 flex-wrap items-center gap-2 text-[13px] text-[#5e7399] lg:justify-end">
                <span className="hidden max-w-[220px] truncate font-medium text-[#70819d] xl:inline">{user.email}</span>
                {view === "users" ? (
                  <KavenixMemberCreateDialog domains={dataset.memberDomainOptions} />
                ) : null}
                <a href={mailEntryUrl} className="om-btn-secondary h-10 rounded-[10px] px-4 text-[13px] text-[#344767]">
                  메일함
                </a>
                <a href={getPublicSiteAbsoluteUrl("/")} className="om-btn-secondary h-10 rounded-[10px] px-4 text-[13px] text-[#344767]">
                  서비스 홈
                </a>
              </div>
            </div>
          </section>

          {view !== "statistics" &&
          view !== "blog" &&
          view !== "sending-servers" &&
          view !== "dkim-reminders" &&
          view !== "domain-assistance" &&
          view !== "promotion-codes" &&
          view !== "app-versions" &&
          !selectedMailbox ? (
            <SummaryRail summary={dataset.summary} />
          ) : null}

          {view === "statistics" ? null : view === "analytics" ? (
            <section className={`border-b border-[#edf1f6] bg-white py-3 ${ADMIN_X_PADDING}`}>
              <MarketingRangeSelector drilldown={marketingDrilldown} rangeDays={rangeDays} />
            </section>
          ) : view === "search" ||
            view === "blog" ||
            view === "sending-servers" ||
            view === "dkim-reminders" ||
            view === "promotion-codes" ||
            view === "app-versions" ||
            selectedMailbox ? null : (
            <section className={`border-b border-[#edf1f6] bg-white py-3 ${ADMIN_X_PADDING}`}>
              <form
                className={`grid w-full gap-2.5 ${
                  view === "charges"
                    ? "sm:grid-cols-[minmax(0,1fr)_minmax(150px,210px)] xl:grid-cols-[minmax(0,1fr)_190px_210px_auto_auto]"
                    : "sm:grid-cols-[minmax(0,1fr)_minmax(150px,220px)] xl:grid-cols-[minmax(0,1fr)_220px_auto_auto]"
                }`}
              >
                <input type="hidden" name="view" value={view} />
                <input
                  type="text"
                  name="q"
                  defaultValue={query}
                  placeholder="이메일, 회사명, 도메인, 주문번호 검색"
                  className="h-10 w-full rounded-[10px] border border-[#dbe5f7] bg-white px-3 text-[13px] text-[#1a2943] outline-none transition-colors placeholder:text-[#97a7c2] focus:border-[#bcd1ff]"
                />
                <select
                  name="domain"
                  defaultValue={selectedDomain}
                  className="h-10 w-full rounded-[10px] border border-[#dbe5f7] bg-white px-3 text-[13px] text-[#1a2943] outline-none transition-colors focus:border-[#bcd1ff]"
                >
                  <option value="">전체 도메인</option>
                  {dataset.domainOptions.map((domain) => (
                    <option key={domain} value={domain}>
                      {domain}
                    </option>
                  ))}
                </select>
                {view === "charges" ? (
                  <select
                    name="chargeFilter"
                    defaultValue={dataset.chargeFilter}
                    className="h-10 w-full rounded-[10px] border border-[#dbe5f7] bg-white px-3 text-[13px] text-[#1a2943] outline-none transition-colors focus:border-[#bcd1ff] sm:col-span-2 xl:col-span-1"
                  >
                    <option value="all">전체 결제</option>
                    <option value="withdrawal">청약철회 요청 포함</option>
                    <option value="withdrawal_pending_review">청약철회 검토 대기</option>
                    <option value="withdrawal_approved">청약철회 승인 후 처리대기</option>
                    <option value="refunded">환불 진행/완료</option>
                  </select>
                ) : (
                  <input type="hidden" name="chargeFilter" value={dataset.chargeFilter} />
                )}
                <button type="submit" className="om-btn-primary h-10 rounded-[10px] px-4 text-[13px] shadow-none">
                  조회
                </button>
                <Link
                  href={buildAdminHref({ view })}
                  className="om-btn-secondary h-10 rounded-[10px] px-4 text-[13px] text-[#344767] shadow-none"
                >
                  초기화
                </Link>
              </form>
            </section>
          )}

          <section className="bg-white">
            {view === "statistics" && statistics ? (
              <KavenixStatisticsDashboard initialData={statistics} />
            ) : view === "analytics" && analytics ? (
              <MarketingAnalyticsDashboard analytics={analytics} />
            ) : view === "search" && googleSearchConsoleAnalytics ? (
              <KavenixGoogleSearchConsoleDashboard
                analytics={googleSearchConsoleAnalytics}
                status={googleSearchConsoleStatus}
              />
            ) : view === "blog" ? (
              <KavenixBlogEditor
                initialPostId={Number.isInteger(selectedBlogPostId) && Number(selectedBlogPostId) > 0 ? selectedBlogPostId : null}
                initialQuery={newBlogQuery}
                posts={marketingBlogPosts ?? []}
                searchConsole={googleSearchConsoleBlogStatus}
              />
            ) : view === "users" ? (
              <UsersTable rows={dataset.users} query={query} />
            ) : view === "domains" ? (
              <DomainsTable
                rows={dataset.domains}
                query={query}
                sendingServers={dataset.sendingServers}
              />
            ) : view === "sending-servers" ? (
              <KavenixSendingServerDashboard initialServers={dataset.sendingServers} />
            ) : view === "dkim-reminders" ? (
              <KavenixDkimReminderDashboard
                domainConnectionUrl={getMailAbsoluteUrl("/mail?panel=setup&section=domain")}
                initialRows={dkimReminderRows}
                initialTemplates={DEFAULT_DKIM_REMINDER_TEMPLATES}
              />
            ) : view === "domain-assistance" ? (
              <KavenixDomainAssistanceDashboard initialRows={domainAssistanceRequests ?? []} />
            ) : view === "promotion-codes" ? (
              <KavenixPromotionCodeDashboard initialCodes={promotionCodes ?? []} />
            ) : view === "app-versions" ? (
              <KavenixAppVersionDashboard />
            ) : view === "mailboxes" ? (
              selectedMailbox ? (
                <AdminMailboxViewer
                  data={selectedMailboxData}
                  mailbox={selectedMailbox}
                />
              ) : (
                <MailboxesTable rows={dataset.mailboxes} query={query} selectedDomain={selectedDomain} />
              )
            ) : (
              <ChargesTable rows={dataset.charges} query={query} />
            )}
          </section>
        </main>
      </div>
    </div>
  );
}
