import React, { useEffect, useRef } from 'react'
import { createPortal } from 'react-dom'
import { Button, type ButtonVariant } from './Button'

// ─── Modal ────────────────────────────────────────────────────────────────────

export interface ModalProps {
  open: boolean
  onClose: () => void
  title?: string
  children: React.ReactNode
  footer?: React.ReactNode
  size?: 'sm' | 'md' | 'lg'
}

const sizeClass = { sm: 'max-w-sm', md: 'max-w-md', lg: 'max-w-lg' }

export const Modal: React.FC<ModalProps> = ({
  open,
  onClose,
  title,
  children,
  footer,
  size = 'md',
}) => {
  const dialogRef = useRef<HTMLDivElement>(null)

  useEffect(() => {
    if (!open) return
    const handleKey = (e: KeyboardEvent) => {
      if (e.key === 'Escape') onClose()
    }
    document.addEventListener('keydown', handleKey)
    document.body.style.overflow = 'hidden'
    return () => {
      document.removeEventListener('keydown', handleKey)
      document.body.style.overflow = ''
    }
  }, [open, onClose])

  useEffect(() => {
    if (!open || !dialogRef.current) return
    const el = dialogRef.current
    const focusable = el.querySelectorAll<HTMLElement>(
      'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
    )
    const first = focusable[0]
    const last = focusable[focusable.length - 1]
    first?.focus()
    const trap = (e: KeyboardEvent) => {
      if (e.key !== 'Tab') return
      if (e.shiftKey) {
        if (document.activeElement === first) { e.preventDefault(); last?.focus() }
      } else {
        if (document.activeElement === last) { e.preventDefault(); first?.focus() }
      }
    }
    document.addEventListener('keydown', trap)
    return () => document.removeEventListener('keydown', trap)
  }, [open])

  if (!open) return null

  return createPortal(
    <div
      className="fixed inset-0 bg-slate-900/40 z-50 flex items-center justify-center"
      onClick={(e) => e.target === e.currentTarget && onClose()}
    >
      <div
        ref={dialogRef}
        role="dialog"
        aria-modal="true"
        aria-labelledby={title ? 'modal-title' : undefined}
        className={`bg-white rounded-2xl p-6 shadow-soft-xl w-full ${sizeClass[size]} mx-4`}
      >
        <div className="flex justify-between items-center mb-4">
          {title && (
            <h2 id="modal-title" className="text-base font-extrabold text-slate-900">
              {title}
            </h2>
          )}
          <Button
            variant="ghost"
            size="sm"
            onClick={onClose}
            aria-label="닫기"
            leftIcon="close"
            className="ml-auto"
          />
        </div>

        <div className="text-body-sm text-slate-500 leading-relaxed">{children}</div>

        {footer && <div className="flex justify-end gap-2 mt-5">{footer}</div>}
      </div>
    </div>,
    document.body
  )
}

// ─── SectionedModal ───────────────────────────────────────────────────────────
// 헤더/바디/푸터가 border로 분리되고 children이 자유롭게 들어가는 모달.
// 풍부한 콘텐츠(폼, 리스트, 테이블, 경고/안내 박스 등)에 적합.

const sectionedSizeClass = {
  sm: 'max-w-md',     // 448px
  md: 'max-w-lg',     // 512px
  lg: 'max-w-2xl',    // 672px
  xl: 'max-w-4xl',    // 896px
  '2xl': 'max-w-6xl', // 1152px
}

export interface SectionedModalProps {
  open: boolean
  onClose: () => void
  /** 헤더 좌측 제목. ReactNode 허용 (아이콘+텍스트 조합 등) */
  title?: React.ReactNode
  /** 제목 좌측에 표시할 material icon 이름 (선택) */
  headerIcon?: string
  /** 제목 우측에 표시할 부가 메타 (파일명·페이지 정보 등) */
  headerExtra?: React.ReactNode
  /** 모달 본문 */
  children: React.ReactNode
  /** 푸터 영역. 비우면 footer 자체가 렌더되지 않음 */
  footer?: React.ReactNode
  /** 푸터 정렬. 기본 'end' (우측 정렬) */
  footerAlign?: 'start' | 'end' | 'between'
  /** 모달 크기. 기본 'md'. xl/2xl은 풍부한 콘텐츠용 */
  size?: 'sm' | 'md' | 'lg' | 'xl' | '2xl'
  /** body 영역 className override (기본 'px-5 py-4'). padding/style 커스터마이징용 */
  bodyClassName?: string
}

export const SectionedModal: React.FC<SectionedModalProps> = ({
  open,
  onClose,
  title,
  headerIcon,
  headerExtra,
  children,
  footer,
  footerAlign = 'end',
  size = 'md',
  bodyClassName = 'px-5 py-4',
}) => {
  const dialogRef = useRef<HTMLDivElement>(null)

  useEffect(() => {
    if (!open) return
    const handleKey = (e: KeyboardEvent) => {
      if (e.key === 'Escape') onClose()
    }
    document.addEventListener('keydown', handleKey)
    document.body.style.overflow = 'hidden'
    return () => {
      document.removeEventListener('keydown', handleKey)
      document.body.style.overflow = ''
    }
  }, [open, onClose])

  useEffect(() => {
    if (!open || !dialogRef.current) return
    const el = dialogRef.current
    const focusable = el.querySelectorAll<HTMLElement>(
      'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
    )
    const first = focusable[0]
    const last = focusable[focusable.length - 1]
    first?.focus()
    const trap = (e: KeyboardEvent) => {
      if (e.key !== 'Tab') return
      if (e.shiftKey) {
        if (document.activeElement === first) { e.preventDefault(); last?.focus() }
      } else {
        if (document.activeElement === last) { e.preventDefault(); first?.focus() }
      }
    }
    document.addEventListener('keydown', trap)
    return () => document.removeEventListener('keydown', trap)
  }, [open])

  if (!open) return null

  const footerJustify =
    footerAlign === 'start' ? 'justify-start' :
    footerAlign === 'between' ? 'justify-between' :
    'justify-end'

  return createPortal(
    <div
      className="fixed inset-0 bg-slate-900/40 z-50 flex items-center justify-center"
      onClick={(e) => e.target === e.currentTarget && onClose()}
    >
      <div
        ref={dialogRef}
        role="dialog"
        aria-modal="true"
        aria-labelledby={title ? 'sectioned-modal-title' : undefined}
        className={`bg-white rounded-[14px] shadow-soft-md w-full ${sectionedSizeClass[size]} mx-4 max-h-[95vh] flex flex-col`}
      >
        {/* Header */}
        <div className="flex items-center justify-between px-5 py-4 border-b border-slate-100 shrink-0">
          <div className="flex items-center gap-1.5 min-w-0">
            {headerIcon && (
              <span className="material-symbols-outlined text-h2 text-teal-500 shrink-0">{headerIcon}</span>
            )}
            {title && (
              <h2 id="sectioned-modal-title" className="text-body-md font-bold text-slate-900 truncate">
                {title}
              </h2>
            )}
            {headerExtra && (
              <div className="text-caption text-slate-400 ml-2 truncate">{headerExtra}</div>
            )}
          </div>
          <Button
            variant="ghost"
            size="sm"
            onClick={onClose}
            aria-label="닫기"
            leftIcon="close"
            className="w-7 h-7 p-0 shrink-0"
          />
        </div>

        {/* Body */}
        <div className={`flex-1 overflow-y-auto ${bodyClassName}`}>
          {children}
        </div>

        {/* Footer */}
        {footer && (
          <div className={`flex items-center ${footerJustify} gap-2 px-5 py-3.5 border-t border-slate-100 shrink-0`}>
            {footer}
          </div>
        )}
      </div>
    </div>,
    document.body
  )
}

// ─── ConfirmModal ─────────────────────────────────────────────────────────────

type ConfirmVariant = 'delete' | 'reset' | 'confirm'

const confirmConfig: Record<
  ConfirmVariant,
  { icon: string; iconBg: string; iconColor: string; btnVariant: ButtonVariant; btnClassName?: string }
> = {
  delete: {
    icon: 'warning',
    iconBg: 'bg-red-50',
    iconColor: 'text-red-500',
    btnVariant: 'danger',
  },
  reset: {
    icon: 'restart_alt',
    iconBg: 'bg-amber-50',
    iconColor: 'text-amber-500',
    btnVariant: 'primary',
    btnClassName: 'bg-amber-500 hover:bg-amber-600 active:bg-amber-700',
  },
  confirm: {
    icon: 'help',
    iconBg: 'bg-teal-50',
    iconColor: 'text-teal-500',
    btnVariant: 'primary',
  },
}

export interface ConfirmModalProps {
  open: boolean
  onClose: () => void
  onConfirm: () => void
  title: string
  description: string
  confirmLabel?: string
  cancelLabel?: string
  variant?: ConfirmVariant
}

export const ConfirmModal: React.FC<ConfirmModalProps> = ({
  open,
  onClose,
  onConfirm,
  title,
  description,
  confirmLabel = '확인',
  cancelLabel = '취소',
  variant = 'confirm',
}) => {
  const cfg = confirmConfig[variant]

  useEffect(() => {
    if (!open) return
    const handleKey = (e: KeyboardEvent) => {
      if (e.key === 'Escape') onClose()
    }
    document.addEventListener('keydown', handleKey)
    document.body.style.overflow = 'hidden'
    return () => {
      document.removeEventListener('keydown', handleKey)
      document.body.style.overflow = ''
    }
  }, [open, onClose])

  if (!open) return null

  return createPortal(
    <div
      className="fixed inset-0 bg-slate-900/40 z-50 flex items-center justify-center"
      onClick={(e) => e.target === e.currentTarget && onClose()}
    >
      <div
        role="alertdialog"
        aria-modal="true"
        aria-labelledby="confirm-title"
        aria-describedby="confirm-desc"
        className="bg-white rounded-2xl p-6 shadow-soft-xl w-full max-w-md mx-4"
      >
        <div className={`w-12 h-12 rounded-full ${cfg.iconBg} flex items-center justify-center mx-auto mb-4`}>
          <span className={`material-symbols-outlined ${cfg.iconColor} text-h1`}>{cfg.icon}</span>
        </div>

        <h2 id="confirm-title" className="text-base font-extrabold text-slate-900 text-center mb-2">
          {title}
        </h2>
        <p id="confirm-desc" className="text-body-sm text-slate-500 leading-relaxed text-center mb-6">
          {description}
        </p>

        <div className="flex gap-2">
          <Button variant="ghost" size="md" onClick={onClose} className="flex-1">
            {cancelLabel}
          </Button>
          <Button
            variant={cfg.btnVariant}
            size="md"
            onClick={() => { onConfirm(); onClose(); }}
            className={`flex-1 ${cfg.btnClassName ?? ''}`}
          >
            {confirmLabel}
          </Button>
        </div>
      </div>
    </div>,
    document.body
  )
}
