"use client";

import { useEffect, useEffectEvent, useRef, useState, type FormEvent, type ReactNode } from "react";
import { createPortal } from "react-dom";
import type { MailboxContact, MailboxSenderMoveRule, MailboxSenderProfile } from "@/lib/official-mail";

export type MailSenderClassificationInput = {
  moveExistingMessages: boolean;
  previousTargetFolder?: string;
  moveFolderCounts?: MailboxSenderProfile["moveFolderCounts"];
  ruleId: number | null;
  senderAddress: string;
  targetFolder: string;
};

type MailSenderProfilePopoverProps = {
  anchorElement: HTMLElement;
  currentFolder: string;
  displayName: string;
  email: string;
  onClose: () => void;
  onCompose: (email: string) => void;
  onMailboxChanged: () => void;
  onNavigate: (href: string) => void;
  onSaveClassification?: (input: MailSenderClassificationInput) => Promise<MailboxSenderMoveRule>;
};

function Icon({ children }: { children: ReactNode }) {
  return <span className="flex h-7 items-center justify-center text-[#253650]">{children}</span>;
}

const svgProps = { className: "h-[21px] w-[21px]", fill: "none", stroke: "currentColor", strokeLinecap: "round" as const, strokeLinejoin: "round" as const, strokeWidth: 1.7, viewBox: "0 0 24 24" };

export function MailSenderProfilePopover(props: MailSenderProfilePopoverProps) {
  const { anchorElement, displayName, email, onClose, onCompose, onMailboxChanged, onNavigate } = props;
  const [profile, setProfile] = useState<MailboxSenderProfile | null>(null);
  const [loading, setLoading] = useState(true);
  const [busy, setBusy] = useState(false);
  const [panel, setPanel] = useState<"classify" | "confirm-delete" | "contact" | null>(null);
  const [folder, setFolder] = useState("");
  const [moveExisting, setMoveExisting] = useState(false);
  const [contactName, setContactName] = useState(displayName === email ? "" : displayName);
  const [contactCompany, setContactCompany] = useState("");
  const [contactGroup, setContactGroup] = useState("");
  const [notice, setNotice] = useState("");
  const [position, setPosition] = useState({ left: 16, top: 80 });
  const popoverRef = useRef<HTMLDivElement>(null);

  useEffect(() => {
    const updatePosition = () => {
      const rect = anchorElement.getBoundingClientRect();
      const width = 330;
      const estimatedHeight = 500;
      const nextTop = rect.bottom + 8 + estimatedHeight > window.innerHeight
        ? Math.max(12, rect.top - estimatedHeight - 8)
        : rect.bottom + 8;
      setPosition({
        left: Math.max(12, Math.min(window.innerWidth - width - 12, rect.left)),
        top: nextTop
      });
    };
    updatePosition();
    window.addEventListener("resize", updatePosition);
    window.addEventListener("scroll", updatePosition, true);
    return () => {
      window.removeEventListener("resize", updatePosition);
      window.removeEventListener("scroll", updatePosition, true);
    };
  }, [anchorElement]);

  const loadProfile = async () => {
    setLoading(true);
    try {
      const response = await fetch(`/api/mailbox/contacts?sender=${encodeURIComponent(email)}`, { cache: "no-store" });
      const payload = (await response.json().catch(() => null)) as { ok?: boolean; profile?: MailboxSenderProfile } | null;
      if (!response.ok || !payload?.ok || !payload.profile) throw new Error("profile-load-failed");
      setProfile(payload.profile);
      setFolder(payload.profile.moveRule?.targetFolderSystemName ?? payload.profile.folders[0]?.systemName ?? "");
      setContactName(payload.profile.contact?.displayName || (displayName === email ? "" : displayName));
      setContactCompany(payload.profile.contact?.companyName ?? "");
      setContactGroup(payload.profile.contact?.groupName ?? "");
    } catch {
      setNotice("발신자 정보를 불러오지 못했습니다.");
    } finally { setLoading(false); }
  };

  const loadProfileEffect = useEffectEvent(loadProfile);

  useEffect(() => {
    const timer = window.setTimeout(() => void loadProfileEffect(), 0);
    return () => window.clearTimeout(timer);
  }, [email]);

  useEffect(() => {
    const handlePointer = (event: MouseEvent) => {
      const target = event.target;
      if (target instanceof Node && !popoverRef.current?.contains(target) && !anchorElement.contains(target)) onClose();
    };
    const handleKey = (event: KeyboardEvent) => { if (event.key === "Escape") onClose(); };
    document.addEventListener("mousedown", handlePointer);
    document.addEventListener("keydown", handleKey);
    return () => { document.removeEventListener("mousedown", handlePointer); document.removeEventListener("keydown", handleKey); };
  }, [anchorElement, onClose]);

  const saveContact = async (input?: { isVip?: boolean }) => {
    setBusy(true);
    setNotice("");
    try {
      const response = await fetch("/api/mailbox/contacts", {
        body: JSON.stringify({
          autoMoveFolder: profile?.moveRule?.targetFolderSystemName ?? null,
          companyName: contactCompany,
          contactId: profile?.contact?.id ?? null,
          displayName: contactName,
          email,
          groupName: contactGroup,
          isVip: input?.isVip ?? profile?.contact?.isVip ?? false,
          memo: profile?.contact?.memo ?? "",
          phone: profile?.contact?.phone ?? ""
        }),
        headers: { "Content-Type": "application/json" }, method: "POST"
      });
      const payload = await response.json().catch(() => null) as { ok?: boolean; contact?: MailboxContact; message?: string } | null;
      if (!response.ok || !payload?.ok || !payload.contact) throw new Error(payload?.message || "주소록을 저장하지 못했습니다.");
      setProfile((current) => current ? { ...current, contact: payload.contact! } : current);
      setPanel(null);
      setNotice(input?.isVip !== undefined ? (input.isVip ? "VIP로 지정했습니다." : "VIP 지정을 해제했습니다.") : "주소록을 저장했습니다.");
      onMailboxChanged();
    } catch (error) { setNotice(error instanceof Error ? error.message : "주소록을 저장하지 못했습니다."); } finally { setBusy(false); }
  };

  const setSpamDisposition = async () => {
    setBusy(true);
    setNotice("");
    try {
      const action = profile?.disposition === "spam" ? "allow" : "spam";
      const response = await fetch("/api/mailbox/spam-rules", {
        body: JSON.stringify({ action, kind: "sender", moveExistingMessages: true, senderAddress: email, targetFolder: "inbox" }),
        headers: { "Content-Type": "application/json" }, method: "POST"
      });
      const payload = await response.json().catch(() => null) as { ok?: boolean; message?: string } | null;
      if (!response.ok || !payload?.ok) throw new Error(payload?.message || "스팸 설정을 처리하지 못했습니다.");
      setProfile((current) => current ? { ...current, disposition: action } : current);
      setNotice(action === "spam" ? "발신자를 차단했습니다." : "발신자 차단을 해제했습니다.");
      onMailboxChanged();
    } catch (error) { setNotice(error instanceof Error ? error.message : "스팸 설정을 처리하지 못했습니다."); } finally { setBusy(false); }
  };

  const saveClassification = async () => {
    if (!folder) return;
    setBusy(true);
    setNotice("");
    try {
      const input = { moveExistingMessages: moveExisting, moveFolderCounts: profile?.moveFolderCounts, previousTargetFolder: profile?.moveRule?.targetFolderSystemName, ruleId: profile?.moveRule?.id ?? null, senderAddress: email, targetFolder: folder };
      let rule: MailboxSenderMoveRule;
      if (props.onSaveClassification) {
        rule = await props.onSaveClassification(input);
      } else {
        const response = await fetch("/api/mailbox/move-rules", {
          body: JSON.stringify(input), headers: { "Content-Type": "application/json" }, method: "POST"
        });
        const payload = await response.json().catch(() => null) as { ok?: boolean; rule?: MailboxSenderMoveRule; message?: string } | null;
        if (!response.ok || !payload?.ok || !payload.rule) throw new Error(payload?.message || "자동분류를 저장하지 못했습니다.");
        rule = payload.rule;
      }
      setProfile((current) => current ? { ...current, moveRule: rule } : current);
      setPanel(null);
      setNotice("자동분류를 저장했습니다.");
      if (!props.onSaveClassification) onMailboxChanged();
    } catch (error) { setNotice(error instanceof Error ? error.message : "자동분류를 저장하지 못했습니다."); } finally { setBusy(false); }
  };

  const deleteAll = async () => {
    setBusy(true);
    setNotice("");
    try {
      const response = await fetch("/api/mailbox/sender-actions", {
        body: JSON.stringify({ action: "trash-all", senderAddress: email }),
        headers: { "Content-Type": "application/json" }, method: "POST"
      });
      const payload = await response.json().catch(() => null) as { ok?: boolean; message?: string; result?: { movedCount?: number } } | null;
      if (!response.ok || !payload?.ok) throw new Error(payload?.message || "보낸 사람의 메일을 삭제하지 못했습니다.");
      setPanel(null);
      setNotice(`${payload.result?.movedCount ?? 0}개의 메일을 휴지통으로 이동했습니다.`);
      onMailboxChanged();
    } catch (error) { setNotice(error instanceof Error ? error.message : "보낸 사람의 메일을 삭제하지 못했습니다."); } finally { setBusy(false); }
  };

  const copyAddress = async () => {
    try {
      await navigator.clipboard.writeText(email);
      setNotice("이메일 주소를 복사했습니다.");
    } catch {
      setNotice("주소를 복사하지 못했습니다. 이메일 주소를 선택해 복사해주세요.");
    }
  };

  const searchHref = (field: "correspondent" | "from" | "to") => `/mail?folder=all&field=${field}&q=${encodeURIComponent(email)}&page=1`;
  const navigate = (href: string) => { onClose(); onNavigate(href); };

  const content = (
    <div ref={popoverRef} data-sender-profile-popover="true" data-sender-menu-root="true" data-row-action-stop="true" onClick={(event) => event.stopPropagation()} onMouseDown={(event) => event.stopPropagation()} onPointerDown={(event) => event.stopPropagation()} onDragStart={(event) => event.stopPropagation()} className="fixed z-[190] w-[330px] max-w-[calc(100vw-24px)] overflow-hidden rounded-[18px] border border-[#dfe8f8] bg-white shadow-[0_28px_70px_rgba(18,32,65,0.2)]" style={{ left: position.left, top: position.top, maxHeight: `calc(100vh - ${Math.max(20, position.top)}px - 12px)` }}>
      {busy ? <div className="absolute inset-0 z-20 flex items-center justify-center bg-white/75 backdrop-blur-[1px]"><span className="h-6 w-6 animate-spin rounded-full border-2 border-[#d8e5ff] border-t-[#2f6df6]" /></div> : null}
      <div className="max-h-[inherit] overflow-y-auto">
        <div className="flex items-start justify-between px-5 pb-3 pt-4"><div className="min-w-0"><p className="truncate text-[18px] font-semibold text-[#202d43]">{profile?.contact?.displayName || displayName || email}</p><p className="mt-1 truncate text-[12px] text-[#687895]">{email}</p></div><button type="button" aria-label="발신자 메뉴 닫기" onClick={onClose} className="flex h-8 w-8 cursor-pointer items-center justify-center rounded-full text-[#6f7c90] hover:bg-[#f3f6fb]"><svg {...svgProps}><path d="m6 6 12 12M18 6 6 18" /></svg></button></div>
        {loading ? <div className="px-5 py-10 text-center text-[12px] text-[#8290a7]">발신자 정보를 불러오고 있습니다.</div> : !profile ? <div className="px-5 py-5"><button type="button" onClick={() => void loadProfile()} className="cursor-pointer text-[13px] font-semibold text-[#2f6df6]">다시 시도</button></div> : panel === "contact" ? (
          <form onSubmit={(event: FormEvent) => { event.preventDefault(); void saveContact(); }} className="border-t border-[#edf2fb] px-5 py-4"><p className="text-[13px] font-semibold text-[#263754]">주소록 정보</p><div className="mt-3 space-y-2"><input value={contactName} onChange={(event) => setContactName(event.target.value)} placeholder="이름" className="h-10 w-full rounded-[10px] border border-[#dbe5f7] px-3 text-[13px] outline-none placeholder:text-[12px] focus:border-[#9cbcff]" /><input value={contactCompany} onChange={(event) => setContactCompany(event.target.value)} placeholder="회사" className="h-10 w-full rounded-[10px] border border-[#dbe5f7] px-3 text-[13px] outline-none placeholder:text-[12px] focus:border-[#9cbcff]" /><input value={contactGroup} onChange={(event) => setContactGroup(event.target.value)} placeholder="그룹" className="h-10 w-full rounded-[10px] border border-[#dbe5f7] px-3 text-[13px] outline-none placeholder:text-[12px] focus:border-[#9cbcff]" /></div><div className="mt-4 flex justify-end gap-2"><button type="button" onClick={() => setPanel(null)} className="om-btn-secondary h-9 cursor-pointer rounded-[9px] px-3 text-[12px]">취소</button><button type="submit" className="om-btn-primary h-9 cursor-pointer rounded-[9px] px-4 text-[12px]">저장</button></div></form>
        ) : panel === "classify" ? (
          <div className="border-t border-[#edf2fb] px-5 py-4"><p className="text-[13px] font-semibold text-[#263754]">내 메일함으로 자동 분류</p>{(profile?.folders.length ?? 0) > 0 ? <><select value={folder} onChange={(event) => setFolder(event.target.value)} className="mt-3 h-10 w-full cursor-pointer rounded-[10px] border border-[#dbe5f7] bg-white px-3 text-[13px]">{profile?.folders.map((item) => <option key={item.id} value={item.systemName}>{item.name}</option>)}</select><label className="mt-3 flex cursor-pointer items-center gap-2 text-[12px] text-[#536681]"><input type="checkbox" checked={moveExisting} onChange={(event) => setMoveExisting(event.target.checked)} className="h-4 w-4 accent-[#2f6df6]" />이미 받은 메일도 같이 이동</label><div className="mt-4 flex justify-end gap-2"><button type="button" onClick={() => setPanel(null)} className="om-btn-secondary h-9 cursor-pointer rounded-[9px] px-3 text-[12px]">취소</button><button type="button" onClick={() => void saveClassification()} className="om-btn-primary h-9 cursor-pointer rounded-[9px] px-4 text-[12px]">저장</button></div></> : <><p className="mt-2 text-[12px] leading-5 text-[#76869f]">먼저 왼쪽 사이드바에서 내 메일함을 만들어주세요.</p><button type="button" onClick={() => navigate("/mail?panel=setup&section=classification")} className="mt-3 cursor-pointer text-[12px] font-semibold text-[#2f6df6]">자동분류 설정 열기</button></>}</div>
        ) : panel === "confirm-delete" ? (
          <div className="border-t border-[#edf2fb] px-5 py-5 text-center"><p className="text-[15px] font-semibold text-[#263754]">이 사람이 보낸 메일을 모두 삭제할까요?</p><p className="mt-2 text-[12px] leading-5 text-[#76869f]">현재 휴지통에 없는 받은 메일을 모두 휴지통으로 이동합니다.</p><div className="mt-4 flex justify-center gap-2"><button type="button" onClick={() => setPanel(null)} className="om-btn-secondary h-9 cursor-pointer rounded-[9px] px-3 text-[12px]">취소</button><button type="button" onClick={() => void deleteAll()} className="h-9 cursor-pointer rounded-[9px] bg-[#e55264] px-4 text-[12px] font-semibold text-white">모두 삭제</button></div></div>
        ) : (
          <>
            <div className="grid grid-cols-5 border-b border-[#edf2fb] px-3 pb-4 pt-1 text-center">
              <button type="button" onClick={() => void saveContact({ isVip: !(profile?.contact?.isVip ?? false) })} className={`cursor-pointer text-[10px] ${profile?.contact?.isVip ? "font-semibold text-[#2f6df6]" : "text-[#61718b]"}`}><Icon><svg {...svgProps}><path d="M5 9.5h14l-1.2 7.8H6.2z" /><path d="m7 9.5 2-4 3 4 3-4 2 4" /></svg></Icon>VIP지정</button>
              <button type="button" onClick={() => { onClose(); onCompose(email); }} className="cursor-pointer text-[10px] text-[#61718b]"><Icon><svg {...svgProps}><path d="m4 17 1-4 9-9 3 3-9 9z" /><path d="M13 5l3 3M4 20h16" /></svg></Icon>메일쓰기</button>
              <button type="button" onClick={() => setPanel("contact")} className="cursor-pointer text-[10px] text-[#61718b]"><Icon><svg {...svgProps}><circle cx="9" cy="8" r="3" /><path d="M4 19a5 5 0 0 1 10 0M18 8v6M15 11h6" /></svg></Icon>{profile?.contact ? "주소록수정" : "주소록추가"}</button>
              <button type="button" onClick={() => void copyAddress()} className="cursor-pointer text-[10px] text-[#61718b]"><Icon><svg {...svgProps}><rect x="8" y="8" width="10" height="11" rx="2" /><path d="M6 16H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1" /></svg></Icon>주소복사</button>
              <button type="button" onClick={() => void setSpamDisposition()} className={`cursor-pointer text-[10px] ${profile?.disposition === "spam" ? "font-semibold text-[#2f6df6]" : "text-[#61718b]"}`}><Icon><svg {...svgProps}><circle cx="9" cy="8" r="3" /><path d="M4 19a5 5 0 0 1 9-3M17 14l4 4M21 14l-4 4" /></svg></Icon>{profile?.disposition === "spam" ? "차단해제" : "차단"}</button>
            </div>
            <div className="py-2 text-[13px] text-[#33425a]">
              <button type="button" onClick={() => navigate(searchHref("correspondent"))} className="flex w-full cursor-pointer items-center justify-between px-5 py-2 text-left hover:bg-[#f7faff] hover:text-[#2f6df6]"><span>주고받은 메일 보기</span><span>›</span></button>
              <button type="button" onClick={() => navigate(searchHref("from"))} className="flex w-full cursor-pointer items-center justify-between px-5 py-2 text-left hover:bg-[#f7faff] hover:text-[#2f6df6]"><span>보낸 사람으로 검색하기</span><span>›</span></button>
              <button type="button" onClick={() => navigate(searchHref("to"))} className="flex w-full cursor-pointer items-center justify-between px-5 py-2 text-left hover:bg-[#f7faff] hover:text-[#2f6df6]"><span>받는 사람으로 검색하기</span><span>›</span></button>
              <button type="button" onClick={() => setPanel("classify")} className="flex w-full cursor-pointer items-center justify-between px-5 py-2 text-left hover:bg-[#f7faff] hover:text-[#2f6df6]"><span>내 메일함으로 자동 분류하기</span><span>›</span></button>
              <button type="button" onClick={() => setPanel("confirm-delete")} className="flex w-full cursor-pointer items-center px-5 py-2 text-left hover:bg-[#fff7f8] hover:text-[#c2475b]">이 사람이 보낸 메일 모두 삭제</button>
              <button type="button" onClick={() => void saveContact({ isVip: !profile.contact?.isVip })} className="flex w-full cursor-pointer items-center px-5 py-2 text-left hover:bg-[#f7faff] hover:text-[#2f6df6]">{profile.contact?.isVip ? "보낸 메일 강조 해제" : "보낸 메일 강조하기"}</button>
            </div>
          </>
        )}
        {notice ? <p role="status" className="border-t border-[#edf2fb] px-5 py-2.5 text-[11px] text-[#2f6df6]">{notice}</p> : null}
      </div>
    </div>
  );

  return typeof document === "undefined" ? null : createPortal(content, document.body);
}
