"use client";

import Link from "next/link";
import { useEffect, useState } from "react";

import { CloseIconButton } from "@/components/close-icon-button";

type FunnelActor = {
  channel: string;
  companyName: string | null;
  country: string | null;
  domain: string | null;
  email: string | null;
  eventCount: number;
  firstOccurredAt: string | null;
  id: string;
  landingPath: string | null;
  lastOccurredAt: string | null;
  referrer: string | null;
  visitorId: string | null;
};

type FunnelDetail = {
  actorCount: number;
  actors: FunnelActor[];
  eventCount: number;
  rangeDays: number;
  truncated: boolean;
};

type FunnelDetailResponse = {
  detail?: FunnelDetail;
  message?: string;
  ok?: boolean;
};

function formatDateTime(value: string | null) {
  if (!value) return "시각 확인 불가";

  return new Intl.DateTimeFormat("ko-KR", {
    day: "numeric",
    hour: "2-digit",
    hour12: true,
    minute: "2-digit",
    month: "short",
    timeZone: "Asia/Seoul",
    year: "numeric",
  }).format(new Date(value));
}

function FunnelDetailDialog({
  detail: eventDetail,
  eventType,
  label,
  onClose,
  rangeDays,
}: {
  detail: string | null;
  eventType: string;
  label: string;
  onClose: () => void;
  rangeDays: number;
}) {
  const [detail, setDetail] = useState<FunnelDetail | null>(null);
  const [errorMessage, setErrorMessage] = useState<string | null>(null);

  useEffect(() => {
    const controller = new AbortController();
    const params = new URLSearchParams({
      eventType,
      range: String(rangeDays),
    });
    if (eventDetail) params.set("detail", eventDetail);

    fetch(`/api/kavenix/marketing/product-funnel-details?${params.toString()}`, {
      cache: "no-store",
      credentials: "same-origin",
      signal: controller.signal,
    })
      .then(async (response) => {
        const payload = (await response.json().catch(() => null)) as FunnelDetailResponse | null;

        if (!response.ok || !payload?.ok || !payload.detail) {
          throw new Error(payload?.message || "퍼널 상세 대상을 불러오지 못했습니다.");
        }

        setDetail(payload.detail);
      })
      .catch((error) => {
        if (!controller.signal.aborted) {
          setErrorMessage(
            error instanceof Error ? error.message : "퍼널 상세 대상을 불러오지 못했습니다.",
          );
        }
      });

    return () => controller.abort();
  }, [eventDetail, eventType, rangeDays]);

  useEffect(() => {
    const previousOverflow = document.body.style.overflow;

    function handleKeyDown(event: KeyboardEvent) {
      if (event.key === "Escape") onClose();
    }

    document.body.style.overflow = "hidden";
    window.addEventListener("keydown", handleKeyDown);

    return () => {
      document.body.style.overflow = previousOverflow;
      window.removeEventListener("keydown", handleKeyDown);
    };
  }, [onClose]);

  return (
    <div
      className="fixed inset-0 z-[210] flex items-center justify-center bg-[rgba(12,18,31,0.44)] px-3 py-6 sm:px-5 sm:py-8"
      onClick={onClose}
    >
      <div
        role="dialog"
        aria-modal="true"
        aria-labelledby="product-funnel-detail-title"
        className="flex max-h-[calc(100dvh-3rem)] w-full max-w-[820px] flex-col overflow-hidden rounded-[20px] border border-[#dfe8f7] bg-white shadow-[0_28px_80px_rgba(15,23,42,0.22)] sm:max-h-[calc(100dvh-4rem)] sm:rounded-[24px]"
        onClick={(event) => event.stopPropagation()}
      >
        <div className="flex items-start justify-between gap-4 border-b border-[#edf2f8] px-5 py-5 sm:px-6">
          <div className="min-w-0">
            <p className="text-[12px] font-semibold text-[#2f6df6]">최근 {rangeDays}일 퍼널</p>
            <div className="mt-1.5 flex flex-wrap items-end gap-x-3 gap-y-1">
              <h2 id="product-funnel-detail-title" className="text-[21px] font-semibold tracking-[-0.04em] text-[#16233c] sm:text-[24px]">
                {label}
              </h2>
              {detail ? (
                <span className="pb-0.5 text-[13px] font-semibold text-[#61728e]">
                  {detail.actorCount.toLocaleString("ko-KR")}명 · {detail.eventCount.toLocaleString("ko-KR")}회
                </span>
              ) : null}
            </div>
            <p className="mt-2 text-[12px] leading-5 text-[#7a8aa2]">
              같은 계정 또는 방문자 ID는 한 명으로 합칩니다. 가입 전 활동도 이후 확인된 계정과 연결해 표시합니다.
            </p>
          </div>
          <CloseIconButton ariaLabel="퍼널 상세 닫기" onClick={onClose} />
        </div>

        <div className="min-h-[240px] overflow-y-auto px-5 py-2 sm:px-6">
          {!detail && !errorMessage ? (
            <div className="flex min-h-[240px] items-center justify-center gap-2 text-[13px] text-[#74849c]">
              <span className="h-4 w-4 animate-spin rounded-full border-2 border-[#d7e3f7] border-t-[#2f6df6]" />
              상세 대상을 불러오는 중입니다.
            </div>
          ) : null}

          {errorMessage ? (
            <div className="flex min-h-[240px] items-center justify-center text-center text-[13px] leading-6 text-[#b34e62]">
              {errorMessage}
            </div>
          ) : null}

          {detail?.actors.length === 0 ? (
            <div className="flex min-h-[240px] items-center justify-center text-[13px] text-[#7b8ba3]">
              식별 가능한 계정 또는 방문자가 없습니다.
            </div>
          ) : null}

          {detail?.actors.map((actor) => {
            const identity = actor.email
              ?? (actor.visitorId ? `익명 방문자 ${actor.visitorId.slice(0, 12)}` : "식별 정보 없음");
            const accountDetail = [actor.companyName, actor.domain, actor.country]
              .filter(Boolean)
              .join(" · ");
            const sourceDetail = [actor.channel, actor.landingPath, actor.referrer]
              .filter(Boolean)
              .join(" · ");

            return (
              <article key={actor.id} className="border-b border-[#edf2f8] py-4 last:border-b-0">
                <div className="flex items-start justify-between gap-4">
                  <div className="min-w-0">
                    <div className="flex flex-wrap items-center gap-2">
                      <p className="break-all text-[14px] font-semibold leading-6 text-[#223351]">{identity}</p>
                      <span className={`rounded-full px-2 py-0.5 text-[10px] font-semibold ${actor.email ? "bg-[#edf4ff] text-[#2f6df6]" : "bg-[#f2f4f8] text-[#71819a]"}`}>
                        {actor.email ? "가입 계정" : "익명 방문자"}
                      </span>
                    </div>
                    {accountDetail ? (
                      <p className="mt-0.5 break-all text-[12px] leading-5 text-[#71819a]">{accountDetail}</p>
                    ) : null}
                  </div>
                  <span className="shrink-0 rounded-full bg-[#f5f8fd] px-2.5 py-1 text-[11px] font-semibold text-[#5f718e]">
                    {actor.eventCount.toLocaleString("ko-KR")}회
                  </span>
                </div>
                <div className="mt-2 flex flex-wrap items-center gap-x-2 gap-y-1 text-[11px] text-[#60718d]">
                  <span>최근 {formatDateTime(actor.lastOccurredAt)}</span>
                  {actor.eventCount > 1 ? (
                    <span className="inline-flex items-center gap-2">
                      <span className="h-0.5 w-0.5 rounded-full bg-[#aab5c5]" />
                      최초 {formatDateTime(actor.firstOccurredAt)}
                    </span>
                  ) : null}
                  {actor.email ? (
                    <Link
                      href={`/kavenix?view=users&q=${encodeURIComponent(actor.email)}&domain=&chargeFilter=all`}
                      className="ml-auto shrink-0 font-semibold text-[#2f6df6] hover:text-[#245ed6]"
                    >
                      사용자 관리 열기
                    </Link>
                  ) : null}
                </div>
                {sourceDetail ? (
                  <p className="mt-2 break-all text-[11px] leading-5 text-[#8290a7]">{sourceDetail}</p>
                ) : null}
              </article>
            );
          })}
        </div>

        {detail?.truncated ? (
          <p className="border-t border-[#edf2f8] px-5 py-3 text-[11px] text-[#7b8ba3] sm:px-6">
            대상이 많아 최근 200명까지만 표시합니다.
          </p>
        ) : null}
      </div>
    </div>
  );
}

export function KavenixMarketingProductFunnelDetailButton({
  actorCount,
  detail,
  eventCount,
  eventType,
  label,
  rangeDays,
}: {
  actorCount: number;
  detail: string | null;
  eventCount: number;
  eventType: string;
  label: string;
  rangeDays: number;
}) {
  const [open, setOpen] = useState(false);

  return (
    <>
      <button
        type="button"
        aria-label={`${label} ${actorCount.toLocaleString("ko-KR")}명 상세 보기`}
        className="group shrink-0 cursor-pointer text-right text-[11px] text-[#8290a7] transition-colors hover:text-[#2f6df6] focus-visible:rounded-[6px] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[#2f6df6]/30"
        onClick={() => setOpen(true)}
      >
        <strong className="text-[13px] text-[#243555] underline decoration-transparent underline-offset-2 transition-colors group-hover:text-[#2f6df6] group-hover:decoration-[#9bb9f8]">
          {actorCount.toLocaleString("ko-KR")}
        </strong>
        명
        {eventCount > actorCount ? ` · ${eventCount.toLocaleString("ko-KR")}회` : ""}
      </button>
      {open ? (
        <FunnelDetailDialog
          detail={detail}
          eventType={eventType}
          label={label}
          onClose={() => setOpen(false)}
          rangeDays={rangeDays}
        />
      ) : null}
    </>
  );
}
