"use client";

import type { ReactNode, Ref } from "react";
import { cx } from "../../utils";
import { FoxTextButton } from "../fox-text-button";

/** 꼬리가 판의 위에 붙는지 아래에 붙는지. 판이 트리거의 아래/위 어느 쪽에 뜨는지가 따라온다. */
export type FoxPopoverDirection = "top" | "bottom";

/** 꼬리가 판의 가로 어디에 붙는지. */
export type FoxPopoverArrow = "left" | "center" | "right";

export interface FoxPopoverProps {
  /**
   * `top`이면 꼬리가 판 위에 붙는다 — 트리거 아래에 뜨는 말풍선이다.
   * `bottom`이면 꼬리가 판 아래에 붙는다 — 트리거 위에 뜨는 말풍선이다.
   */
  direction?: FoxPopoverDirection;
  /** 꼬리의 가로 위치. 판 가장자리에서 24px 안쪽에 선다(가운데는 예외). */
  arrow?: FoxPopoverArrow;
  /** 굵은 제목 줄. 넘기지 않으면 렌더링하지 않는다. */
  title?: ReactNode;
  /** 제목 아래 본문. 넘기지 않으면 렌더링하지 않는다. */
  message?: ReactNode;
  /** 아래쪽 글자 버튼의 문구(예: "바로가기"). 없으면 버튼을 그리지 않는다. */
  actionLabel?: string;
  /** 글자 버튼을 눌렀을 때. `actionLabel`이 없으면 의미 없다. */
  onAction?: () => void;
  /** 닫기(X)를 눌렀을 때. **필수다** — 시안이 닫기를 항상 그린다. */
  onClose: () => void;
  /** 닫기 버튼을 읽어 줄 이름. X 아이콘은 장식이라 이 글자가 유일한 이름이다. */
  closeLabel?: string;
  /** 참이면 렌더하지 않는다(DOM에 남지 않는다). */
  hidden?: boolean;
  id?: string;
  /** 배치 조정용. 트리거 옆에 놓는 위치와 시안의 폭(360px)을 여기로 덮는다. */
  className?: string;
  ref?: Ref<HTMLDivElement>;
}

const DIRECTION_CLASS: Record<FoxPopoverDirection, string> = {
  top: "fox-popover--top",
  bottom: "fox-popover--bottom",
};

const ARROW_CLASS: Record<FoxPopoverArrow, string> = {
  left: "fox-popover--arrow-left",
  center: "fox-popover--arrow-center",
  right: "fox-popover--arrow-right",
};

/**
 * @fox 팝오버. 꼬리가 달린 말풍선 판이다. 제목·본문·글자 버튼을 담고 오른쪽 위에 닫기가 붙는다.
 *
 * **상태를 갖지 않고 스스로 자리를 잡지도 않는다.** 언제 열리고 닫힐지는 호출부가 정하고,
 * 트리거 옆 어디에 놓을지는 `className`으로 준다 — `direction`·`arrow`는 꼬리가 어디에
 * 붙는지만 정한다(자리가 모자랄 때 위아래를 뒤집는 자동 배치는 없다. 시안이 방향을 값으로
 * 주므로 그 판단은 호출부의 몫이다).
 *
 * ⚠️ 판을 띄우는 방식은 `FoxSelect`·`FoxChip`의 목록과 같다 — 감싼 요소 기준의 일반 흐름이라
 * `overflow: hidden` 조상 안에서는 잘린다. HTML `popover` 속성으로 top layer에 올리는 방법이
 * 있지만, 위치를 잡아 주는 CSS Anchor Positioning이 아직 크롬 계열에만 있어 미룬다 — 옮기게
 * 되면 셀렉트·칩·툴팁까지 한 번에 옮긴다.
 *
 * 꼬리는 **CSS가 그린다** — 이 컴포넌트가 내보내는 것은 빈 요소 하나뿐이다. 시안이 준 SVG는
 * 1px 흰 띠로 판의 1px 테두리를 지우는 구조라 소수 배율 화면에서 이음새에 실선이 비쳤고,
 * 회전한 정사각형을 판에 절반 걸치는 방식으로 바꿨다(까닭은 스타일 파일 상단 참고).
 *
 * ⚠️ 스타일은 이 파일이 import하지 않는다 — 호스트 앱이 `@use "@fox/styles/components"`
 * (또는 개별 파티셜)로 한 번 불러와야 한다.
 */
export function FoxPopover({
  direction = "top",
  arrow = "left",
  title,
  message,
  actionLabel,
  onAction,
  onClose,
  closeLabel = "닫기",
  hidden = false,
  id,
  className,
  ref,
}: FoxPopoverProps) {
  if (hidden) {
    return null;
  }

  // 꼬리는 CSS가 그린다 — 이 요소는 자리만 잡는다(스타일 파일 참고).
  const arrowSlot = (
    <div className="fox-popover__arrow-area" aria-hidden="true">
      <span className="fox-popover__arrow" />
    </div>
  );

  return (
    <div
      ref={ref}
      id={id}
      className={cx(
        "fox-popover",
        DIRECTION_CLASS[direction],
        ARROW_CLASS[arrow],
        className
      )}
    >
      {direction === "top" ? arrowSlot : null}

      <div className="fox-popover__content">
        {title === undefined && message === undefined ? null : (
          <div className="fox-popover__body">
            {title === undefined ? null : (
              <div className="fox-popover__title-row">
                <strong className="fox-popover__title">{title}</strong>
              </div>
            )}
            {message === undefined ? null : (
              <div className="fox-popover__message-row">
                <span className="fox-popover__message">{message}</span>
              </div>
            )}
          </div>
        )}

        {actionLabel ? (
          <FoxTextButton
            type="secondary"
            size="sm"
            label={actionLabel}
            trailingIcon={<i className="fox-ico fox-ico-CaretRight" aria-hidden="true" />}
            onAction={onAction}
            className="fox-popover__action"
          />
        ) : null}

        <button
          type="button"
          className="fox-popover__close"
          aria-label={closeLabel}
          onClick={onClose}
        >
          <i className="fox-ico fox-ico-X" aria-hidden="true" />
        </button>
      </div>

      {direction === "bottom" ? arrowSlot : null}
    </div>
  );
}
