"use client";

import { useRouter } from "next/navigation";
import { useEffect, useRef, useState } from "react";
import type { KavenixAdminDnsRecord } from "@/lib/kavenix-admin";

type KavenixDomainDnsPopoverProps = {
  domain: string;
  domainId: number;
  dkimEnabled: boolean;
  domainStatus: "pending" | "verified" | "failed";
  lastCheckedAt: string | null;
  records: KavenixAdminDnsRecord[];
};

type VerificationResponse = {
  message?: string;
  ok?: boolean;
  verified?: boolean;
};

type DkimRegenerationResponse = {
  message?: string;
  ok?: boolean;
};

type DkimUsageResponse = {
  message?: string;
  ok?: boolean;
};

type PopoverPosition = {
  left: number;
  top: number;
};

function InfoIcon({ 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"
    >
      <circle cx="12" cy="12" r="8" />
      <path d="M12 10.6v5" />
      <path d="M12 7.6h.01" />
    </svg>
  );
}

function CloseIcon({ 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="m7 7 10 10" />
      <path d="M17 7 7 17" />
    </svg>
  );
}

function formatCheckedAt(value: string | null) {
  if (!value) {
    return "검증 전";
  }

  const date = new Date(value);

  if (Number.isNaN(date.getTime())) {
    return "검증 전";
  }

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

function statusMeta(status: "pending" | "verified" | "failed") {
  if (status === "verified") {
    return { className: "bg-[#edf9ef] text-[#20733a]", label: "정상" };
  }

  if (status === "failed") {
    return { className: "bg-[#fff1f1] text-[#d23f3f]", label: "불일치" };
  }

  return { className: "bg-[#f4f7fb] text-[#667792]", label: "확인 전" };
}

export function KavenixDomainDnsPopover({
  domain,
  domainId,
  dkimEnabled: initialDkimEnabled,
  domainStatus,
  lastCheckedAt,
  records,
}: KavenixDomainDnsPopoverProps) {
  const router = useRouter();
  const rootRef = useRef<HTMLDivElement>(null);
  const buttonRef = useRef<HTMLButtonElement>(null);
  const [open, setOpen] = useState(false);
  const [position, setPosition] = useState<PopoverPosition | null>(null);
  const [verificationMessage, setVerificationMessage] = useState<string | null>(null);
  const [verifying, setVerifying] = useState(false);
  const [dkimEnabled, setDkimEnabled] = useState(initialDkimEnabled);
  const [updatingDkimUsage, setUpdatingDkimUsage] = useState(false);
  const [dkimUsageMessage, setDkimUsageMessage] = useState<string | null>(null);
  const [dkimKeySize, setDkimKeySize] = useState<1024 | 2048>(2048);
  const [dkimMessage, setDkimMessage] = useState<string | null>(null);
  const [reissuingDkim, setReissuingDkim] = useState(false);
  const domainStatusMeta = statusMeta(domainStatus);

  function updatePosition() {
    const rect = buttonRef.current?.getBoundingClientRect();

    if (!rect) {
      return;
    }

    const popoverWidth = Math.min(460, window.innerWidth - 24);
    setPosition({
      left: Math.min(Math.max(12, rect.left), window.innerWidth - popoverWidth - 12),
      top: rect.bottom + 8,
    });
  }

  function togglePopover() {
    if (open) {
      setOpen(false);
      return;
    }

    updatePosition();
    setOpen(true);
  }

  async function verifyConnection() {
    if (verifying) {
      return;
    }

    setVerifying(true);
    setVerificationMessage(null);

    try {
      const response = await fetch(`/api/kavenix/domains/${domainId}/verify`, {
        method: "POST",
      });
      const payload = (await response.json()) as VerificationResponse;

      if (!response.ok || payload.ok !== true) {
        throw new Error(payload.message || "연결 상태 확인에 실패했습니다.");
      }

      setVerificationMessage(
        payload.message ||
          (payload.verified
            ? "연결이 정상입니다."
            : "점검을 완료했습니다. 불일치한 항목을 확인해 주세요."),
      );
      router.refresh();
    } catch (error) {
      setVerificationMessage(
        error instanceof Error
          ? error.message
          : "연결 상태 확인에 실패했습니다.",
      );
    } finally {
      setVerifying(false);
    }
  }

  async function reissueDkim() {
    if (reissuingDkim) {
      return;
    }

    if (
      !window.confirm(
        `${domain}의 DKIM 키를 ${dkimKeySize}-bit로 다시 발급할까요?\n\n기존 DKIM 키는 즉시 교체됩니다. 팝업에 표시되는 새 TXT 값을 DNS에 반영한 뒤 연결 상태를 다시 확인해야 합니다.`,
      )
    ) {
      return;
    }

    setReissuingDkim(true);
    setDkimMessage(null);

    try {
      const response = await fetch(`/api/kavenix/domains/${domainId}/dkim`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ keySize: dkimKeySize }),
      });
      const payload = (await response.json()) as DkimRegenerationResponse;

      if (!response.ok || payload.ok !== true) {
        throw new Error(payload.message || "DKIM 키 재발급에 실패했습니다.");
      }

      setDkimMessage(payload.message || "DKIM 키를 새로 발급했습니다.");
      router.refresh();
    } catch (error) {
      setDkimMessage(
        error instanceof Error
          ? error.message
          : "DKIM 키 재발급에 실패했습니다.",
      );
    } finally {
      setReissuingDkim(false);
    }
  }

  async function toggleDkimUsage() {
    if (updatingDkimUsage) {
      return;
    }

    const nextDkimEnabled = !dkimEnabled;

    if (
      !nextDkimEnabled &&
      !window.confirm(
        `${domain}에서 DKIM 검증을 건너뛸까요?\n\nSPF와 DMARC는 계속 필요하며, 외부 수신처에서 스팸 또는 반송될 가능성이 높아질 수 있습니다.`,
      )
    ) {
      return;
    }

    setUpdatingDkimUsage(true);
    setDkimUsageMessage(null);

    try {
      const response = await fetch(`/api/kavenix/domains/${domainId}/dkim-usage`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ enabled: nextDkimEnabled }),
      });
      const payload = (await response.json()) as DkimUsageResponse;

      if (!response.ok || payload.ok !== true) {
        throw new Error(payload.message || "DKIM 사용 설정을 변경하지 못했습니다.");
      }

      setDkimEnabled(nextDkimEnabled);
      setDkimUsageMessage(payload.message || "DKIM 사용 설정을 변경했습니다.");
      router.refresh();
    } catch (error) {
      setDkimUsageMessage(
        error instanceof Error
          ? error.message
          : "DKIM 사용 설정을 변경하지 못했습니다.",
      );
    } finally {
      setUpdatingDkimUsage(false);
    }
  }

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

    const handlePointerDown = (event: PointerEvent) => {
      if (!rootRef.current?.contains(event.target as Node)) {
        setOpen(false);
      }
    };
    const handleViewportChange = () => updatePosition();

    document.addEventListener("pointerdown", handlePointerDown);
    window.addEventListener("resize", handleViewportChange);
    window.addEventListener("scroll", handleViewportChange, true);

    return () => {
      document.removeEventListener("pointerdown", handlePointerDown);
      window.removeEventListener("resize", handleViewportChange);
      window.removeEventListener("scroll", handleViewportChange, true);
    };
  }, [open]);

  return (
    <div ref={rootRef} className="inline-flex">
      <button
        ref={buttonRef}
        type="button"
        aria-label={`${domain} DNS 레코드 보기`}
        aria-expanded={open}
        onClick={togglePopover}
        className="inline-flex h-5 w-5 shrink-0 cursor-pointer items-center justify-center rounded-full text-[#8392aa] transition-colors hover:bg-[#edf4ff] hover:text-[#2f6df6]"
      >
        <InfoIcon className="h-[15px] w-[15px]" />
      </button>

      {open && position ? (
        <section
          role="dialog"
          aria-label={`${domain} DNS 연결 정보`}
          className="fixed z-[100] max-h-[min(620px,calc(100vh-24px))] w-[min(460px,calc(100vw-24px))] overflow-y-auto rounded-[14px] border border-[#dfe8f8] bg-white p-4 text-left shadow-[0_24px_60px_rgba(18,32,65,0.18)]"
          style={{ left: position.left, top: position.top }}
        >
          <div className="flex items-start justify-between gap-3">
            <div className="min-w-0">
              <p className="truncate text-[14px] font-semibold tracking-[-0.03em] text-[#16233c]">
                {domain}
              </p>
              <div className="mt-1.5 flex flex-wrap items-center gap-x-2 gap-y-1 text-[12px] text-[#70819d]">
                <span className={`rounded-full px-2 py-0.5 font-semibold ${domainStatusMeta.className}`}>
                  {domainStatusMeta.label}
                </span>
                <span>최근 점검 {formatCheckedAt(lastCheckedAt)}</span>
              </div>
            </div>
            <button
              type="button"
              aria-label="DNS 정보 닫기"
              onClick={() => setOpen(false)}
              className="inline-flex h-7 w-7 shrink-0 cursor-pointer items-center justify-center rounded-full text-[#8492aa] transition-colors hover:bg-[#f4f7fc] hover:text-[#2f6df6]"
            >
              <CloseIcon className="h-4 w-4" />
            </button>
          </div>

          <div className="mt-4 border-t border-[#edf1f6] pt-3">
            <button
              type="button"
              onClick={verifyConnection}
              disabled={verifying}
              className="inline-flex h-9 w-full items-center justify-center rounded-[10px] bg-[#2f6df6] px-3 text-[12px] font-semibold text-white transition-colors hover:bg-[#245de3] disabled:cursor-not-allowed disabled:bg-[#9dbcfb]"
            >
              {verifying ? "연결 상태 확인 중..." : "연결 상태 확인"}
            </button>
            {verificationMessage ? (
              <p className="mt-2 text-[12px] leading-5 text-[#5f7190]" aria-live="polite">
                {verificationMessage}
              </p>
            ) : null}
          </div>

          <div className="mt-4 border-t border-[#edf1f6] pt-3">
            <div className="flex items-center justify-between gap-3">
              <div>
                <p className="text-[12px] font-semibold text-[#30425f]">DKIM 사용</p>
                <p className="mt-1 text-[11px] leading-4 text-[#7183a1]">
                  미사용 시 DKIM DNS 등록과 검증을 건너뜁니다.
                </p>
              </div>
              <div className="flex items-center gap-2">
                <span className={`text-[11px] font-semibold ${dkimEnabled ? "text-[#91a0b6]" : "text-[#526784]"}`}>
                  미사용
                </span>
                <button
                  type="button"
                  role="switch"
                  aria-checked={dkimEnabled}
                  aria-label={`DKIM ${dkimEnabled ? "사용" : "미사용"}`}
                  onClick={toggleDkimUsage}
                  disabled={updatingDkimUsage}
                  className={`relative h-6 w-11 shrink-0 rounded-full transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[#8db8ff] focus-visible:ring-offset-2 disabled:cursor-not-allowed ${
                    dkimEnabled ? "bg-[#2f6df6]" : "bg-[#c8d4e8]"
                  }`}
                >
                  <span
                    className={`absolute left-0.5 top-0.5 h-5 w-5 rounded-full bg-white shadow-[0_1px_4px_rgba(24,52,96,0.28)] transition-transform ${
                      dkimEnabled ? "translate-x-[20px]" : "translate-x-0"
                    }`}
                  />
                </button>
                <span className={`text-[11px] font-semibold ${dkimEnabled ? "text-[#245ac9]" : "text-[#91a0b6]"}`}>
                  사용 (권장)
                </span>
              </div>
            </div>
            {dkimUsageMessage ? (
              <p className="mt-2 text-[12px] leading-5 text-[#5f7190]" aria-live="polite">
                {dkimUsageMessage}
              </p>
            ) : null}
          </div>

          {dkimEnabled ? (
          <div className="mt-4 border-t border-[#edf1f6] pt-3">
            <div className="flex items-center justify-between gap-3">
              <div>
                <p className="text-[12px] font-semibold text-[#30425f]">DKIM 키 재발급</p>
                <p className="mt-1 text-[11px] leading-4 text-[#7183a1]">
                  1024-bit는 긴 TXT를 등록하기 어려운 DNS용 호환 모드입니다.
                </p>
              </div>
              <button
                type="button"
                role="switch"
                aria-checked={dkimKeySize === 1024}
                aria-label={`DKIM 1024-bit 호환 모드 ${dkimKeySize === 1024 ? "사용" : "해제"}`}
                onClick={() => setDkimKeySize((current) => (current === 1024 ? 2048 : 1024))}
                className={`relative h-6 w-11 shrink-0 rounded-full transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[#8db8ff] focus-visible:ring-offset-2 ${
                  dkimKeySize === 1024 ? "bg-[#2f6df6]" : "bg-[#c8d4e8]"
                }`}
              >
                <span
                  className={`absolute left-0.5 top-0.5 h-5 w-5 rounded-full bg-white shadow-[0_1px_4px_rgba(24,52,96,0.28)] transition-transform ${
                    dkimKeySize === 1024 ? "translate-x-0" : "translate-x-[20px]"
                  }`}
                />
              </button>
            </div>
            <div className="mt-3 flex items-center justify-between gap-3">
              <span className="text-[12px] font-semibold text-[#2f6df6]">{dkimKeySize}-bit</span>
              <button
                type="button"
                onClick={reissueDkim}
                disabled={reissuingDkim}
                className="inline-flex h-8 items-center justify-center rounded-[9px] border border-[#d5e2f7] px-3 text-[12px] font-semibold text-[#2f6df6] transition-colors hover:bg-[#f4f8ff] disabled:cursor-not-allowed disabled:text-[#9aa8bf]"
              >
                {reissuingDkim ? "키 발급 중..." : "DKIM 키 재발급"}
              </button>
            </div>
            {dkimMessage ? (
              <p className="mt-2 text-[12px] leading-5 text-[#5f7190]" aria-live="polite">
                {dkimMessage}
              </p>
            ) : null}
          </div>
          ) : null}

          <div className="mt-4 border-t border-[#edf1f6]">
            {records.length > 0 ? (
              records.map((record) => {
                const isDisabledDkimRecord =
                  !dkimEnabled &&
                  record.type === "TXT" &&
                  record.host.endsWith("._domainkey");
                const recordStatusMeta = isDisabledDkimRecord
                  ? { className: "bg-[#f4f7fb] text-[#667792]", label: "미사용" }
                  : statusMeta(record.status);

                return (
                  <div key={`${record.type}-${record.host}`} className="border-b border-[#edf1f6] py-3 last:border-b-0">
                    <div className="flex items-center justify-between gap-3">
                      <div className="flex items-center gap-2">
                        <span className="text-[12px] font-semibold text-[#2f6df6]">{record.type}</span>
                        <span className="text-[12px] text-[#60718e]">호스트 {record.host}</span>
                      </div>
                      <span className={`shrink-0 rounded-full px-2 py-0.5 text-[11px] font-semibold ${recordStatusMeta.className}`}>
                        {recordStatusMeta.label}
                      </span>
                    </div>
                    <p className="mt-2 break-all font-mono text-[12px] leading-5 text-[#31415f]">{record.value}</p>
                    <p className="mt-1.5 text-[11px] text-[#8190a8]">
                      {record.priority === null ? "우선순위 -" : `우선순위 ${record.priority}`} · 최근 확인 {formatCheckedAt(record.lastCheckedAt)}
                    </p>
                  </div>
                );
              })
            ) : (
              <p className="py-4 text-[13px] leading-6 text-[#7284a4]">
                아직 저장된 DNS 레코드가 없습니다.
              </p>
            )}
          </div>
        </section>
      ) : null}
    </div>
  );
}
