"use client";

import { useEffect } from "react";
import { useTabStore } from "@/stores/tabStore";
import { toast } from "sonner";

const HIGHLIGHT_ATTR = "data-validation-highlight";
const ERROR_ATTR = "data-validation-error";
const MSG_WRAPPER_CLASS = "validation-error-msg-wrapper";

type TargetEl = HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement | HTMLButtonElement;

/**
 * 모달 필수 입력 검증 훅 (클릭 인터셉트 방식)
 *
 * 저장/수정/확인 버튼 클릭 시 빈 필수 필드가 있으면:
 *   1. 클릭 이벤트 차단
 *   2. 첫 번째 빈 필드로 포커스 이동 + 하이라이트
 *   3. 빈 필드에 빨간 테두리 유지 (값 입력 시 해제)
 *   4. 토스트 알림 표시
 *
 * 설계: docs/ycshin-node/필수입력항목_자동검증_설계.md
 */
export function useDialogAutoValidation(contentEl: HTMLElement | null) {
  const mode = useTabStore((s) => s.mode);

  useEffect(() => {
    if (mode !== "user") return;

    const el = contentEl;
    if (!el) return;

    const errorFields = new Set<TargetEl>();
    let activated = false; // 첫 저장 시도 이후 true

    function findRequiredFields(): Map<TargetEl, string> {
      const fields = new Map<TargetEl, string>();
      if (!el) return fields;

      el.querySelectorAll("label").forEach((label) => {
        const hasRequiredMark = Array.from(label.querySelectorAll("span")).some(
          (span) => span.textContent?.trim() === "*",
        );
        if (!hasRequiredMark) return;

        const forId = label.getAttribute("for") || (label as HTMLLabelElement).htmlFor;
        let target: TargetEl | null = null;

        if (forId) {
          try {
            const found = el!.querySelector(`#${CSS.escape(forId)}`);
            if (isFormElement(found)) {
              target = found;
            } else if (found) {
              const inner = found.querySelector("input, textarea, select");
              if (isFormElement(inner) && !isHiddenRadixSelect(inner)) {
                target = inner;
              }
              // 숨겨진 Radix select이거나 폼 요소가 없으면 → 트리거 버튼 탐색
              if (!target) {
                const btn = found.querySelector('button[role="combobox"], button[data-slot="select-trigger"]');
                if (btn instanceof HTMLButtonElement) target = btn;
              }
            }
          } catch {
            /* invalid id */
          }
        }

        if (!target) {
          const parent = label.closest('[class*="space-y"]') || label.parentElement;
          if (parent) {
            const inner = parent.querySelector("input, textarea, select");
            if (isFormElement(inner) && !isHiddenRadixSelect(inner)) {
              target = inner;
            }
            if (!target) {
              const btn = parent.querySelector('button[role="combobox"], button[data-slot="select-trigger"]');
              if (btn instanceof HTMLButtonElement) target = btn;
            }
          }
        }

        if (target) {
          const labelText = label.textContent?.replace(/\*/g, "").trim() || "";
          fields.set(target, labelText);
        }
      });

      return fields;
    }

    function isFormElement(el: Element | null): el is HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement {
      return el instanceof HTMLInputElement || el instanceof HTMLTextAreaElement || el instanceof HTMLSelectElement;
    }

    function isHiddenRadixSelect(el: Element): boolean {
      return el instanceof HTMLSelectElement && el.hasAttribute("aria-hidden");
    }

    // 복합 입력 필드(채번 세그먼트 등)의 시각적 테두리 컨테이너 탐지
    // input 자체에 border가 없고 부모가 border를 가진 경우 부모를 반환
    function findBorderContainer(input: TargetEl): HTMLElement {
      const parent = input.parentElement;
      if (parent && parent.classList.contains("border")) {
        return parent;
      }
      return input;
    }

    function isEmpty(input: TargetEl): boolean {
      if (input instanceof HTMLButtonElement) {
        // Radix Select: data-placeholder 속성이 자식 span에 있으면 미선택 상태
        return !!input.querySelector("[data-placeholder]");
      }
      return input.value.trim() === "";
    }

    function isSaveButton(target: HTMLElement): boolean {
      const btn = target.closest("button");
      if (!btn) return false;

      const actionType = btn.getAttribute("data-action-type");
      if (actionType === "save" || actionType === "submit") return true;

      const variant = btn.getAttribute("data-variant");
      if (variant === "default") return true;

      return false;
    }

    function markError(input: TargetEl) {
      const container = findBorderContainer(input);
      container.setAttribute(ERROR_ATTR, "true");
      errorFields.add(input);
      showErrorMsg(input);
    }

    function clearError(input: TargetEl) {
      const container = findBorderContainer(input);
      container.removeAttribute(ERROR_ATTR);
      errorFields.delete(input);
      removeErrorMsg(input);
    }

    // 빈 필수 필드 아래에 경고 문구 삽입 (레이아웃 영향 없는 zero-height wrapper)
    // 복합 입력(채번 세그먼트 등)은 border 컨테이너 바깥에 삽입
    function showErrorMsg(input: TargetEl) {
      const container = findBorderContainer(input);
      if (container.parentElement?.querySelector(`.${MSG_WRAPPER_CLASS}`)) return;

      const wrapper = document.createElement("div");
      wrapper.className = MSG_WRAPPER_CLASS;

      const msg = document.createElement("p");
      msg.textContent = "필수 입력 항목입니다";
      wrapper.appendChild(msg);

      container.insertAdjacentElement("afterend", wrapper);
    }

    function removeErrorMsg(input: TargetEl) {
      const container = findBorderContainer(input);
      const wrapper = container.parentElement?.querySelector(`.${MSG_WRAPPER_CLASS}`);
      if (wrapper) wrapper.remove();
    }

    function highlightField(input: TargetEl) {
      const container = findBorderContainer(input);
      container.setAttribute(HIGHLIGHT_ATTR, "true");
      container.addEventListener("animationend", () => container.removeAttribute(HIGHLIGHT_ATTR), { once: true });

      if (input instanceof HTMLButtonElement) {
        input.click();
      } else {
        input.focus();
      }
    }

    // 첫 저장 시도 이후: 빈 필드 → 에러 유지/재적용, 값 있으면 해제
    function syncErrors() {
      if (!activated) return;
      const fields = findRequiredFields();
      for (const [input] of fields) {
        if (isEmpty(input)) {
          markError(input);
        } else {
          clearError(input);
        }
      }
    }

    function handleClick(e: Event) {
      const target = e.target as HTMLElement;
      if (!isSaveButton(target)) return;

      const fields = findRequiredFields();
      if (fields.size === 0) return;

      let firstEmpty: TargetEl | null = null;
      let firstEmptyLabel = "";

      for (const [input, label] of fields) {
        if (isEmpty(input)) {
          markError(input);
          if (!firstEmpty) {
            firstEmpty = input;
            firstEmptyLabel = label;
          }
        } else {
          clearError(input);
        }
      }

      if (!firstEmpty) return;

      activated = true;
      e.stopPropagation();
      e.preventDefault();

      highlightField(firstEmpty);
      toast.error(`${firstEmptyLabel} 항목을 입력해주세요`);
    }

    // V2Select는 input/change 이벤트가 없으므로 DOM 변경 감지로 에러 동기화
    const observer = new MutationObserver(syncErrors);
    observer.observe(el, { childList: true, subtree: true, attributes: true, attributeFilter: ["data-placeholder"] });

    el.addEventListener("click", handleClick, true);
    el.addEventListener("input", syncErrors);
    el.addEventListener("change", syncErrors);

    return () => {
      el.removeEventListener("click", handleClick, true);
      el.removeEventListener("input", syncErrors);
      el.removeEventListener("change", syncErrors);
      observer.disconnect();

      el.querySelectorAll(`[${HIGHLIGHT_ATTR}]`).forEach((node) => node.removeAttribute(HIGHLIGHT_ATTR));
      el.querySelectorAll(`[${ERROR_ATTR}]`).forEach((node) => node.removeAttribute(ERROR_ATTR));
      el.querySelectorAll(`.${MSG_WRAPPER_CLASS}`).forEach((node) => node.remove());
    };
  }, [mode, contentEl]);
}
