import { useCallback, useEffect, useId, useRef, useState } from 'react';
import { X } from 'lucide-react';
import Button from './Button';

/** 外阴影 + 1px 内描边（fill-default），合并为同一 box-shadow（Tailwind 多 shadow 类会互斥） */
const PANEL_OUTER_SHADOW = {
  center: 'var(--shadow-lg)',
  fullscreen: 'var(--shadow-xl)',
};
const PANEL_INSET_STROKE = 'inset 0 0 0 1px var(--color-fill)';

function resolvePanelBoxShadow(layout, styleBoxShadow) {
  if (styleBoxShadow) return styleBoxShadow;
  return `${PANEL_OUTER_SHADOW[layout]}, ${PANEL_INSET_STROKE}`;
}

/* ── 布局变体 → 面板几何 ── */
const LAYOUT_CLASS = {
  /* 居中浮层：受 size 控制最大宽度，最大高度 85vh */
  center: 'max-h-[85vh] rounded-lg',
  /* 全屏弹窗：高度 = 容器高度 - 24px，宽度撑满，底部对齐，顶部圆角；外层须是 flex-col 定高容器 */
  fullscreen: 'h-[calc(100%-24px)] rounded-t-lg rounded-b-none',
};

/* ── 尺寸 → 面板最大宽度（仅 layout='center' 时生效） ── */
const SIZE_CLASS = {
  sm: 'max-w-[450px]',
  md: 'max-w-[684px]',
  lg: 'max-w-[920px]',
};

/* ── 布局变体 → 内容区高度策略 ── */
const BODY_CLASS = {
  center: 'flex-1 min-h-[200px] w-full overflow-y-auto',
  fullscreen: 'flex-1 min-h-0 w-full overflow-y-auto',
};

/* ── 面板容器基础样式 ── */
const PANEL_BASE = [
  'flex flex-col items-stretch w-full min-w-0',
  'bg-surface px-6',
].join(' ');

/* ── 头部 / 内容 / 底部 ── */
const HEADER = 'flex shrink-0 w-full items-start justify-between gap-2 py-6';
const HEADER_DRAGGABLE = 'cursor-grab touch-none active:cursor-grabbing';
const TITLE = 'm-0 text-lg [font-weight:var(--font-semibold)] leading-6 text-foreground';
const SUBTITLE = 'm-0 text-sm font-normal leading-6 text-foreground-muted';

const FOOTER = 'flex shrink-0 w-full flex-col py-6';
const FOOTER_ROW =
  'flex w-full flex-wrap items-center justify-between gap-x-6 gap-y-2';
const FOOTER_HINT =
  'm-0 min-w-[7.5rem] flex-1 text-xs font-normal leading-4 text-foreground-secondary';
const ACTIONS = 'flex shrink-0 items-center justify-end gap-3';
const BODY_BOTTOM_GAP = 'shrink-0 h-6';

/**
 * Modal — 模态对话框面板（仅面板本体，遮罩与视口级定位由外层处理）
 *
 * **默认唤起位置（layout='center'）**：页面/视口正中。业务页须由外层容器负责遮罩与居中，
 * 推荐 `<div className="fixed inset-0 flex items-center justify-center bg-overlay p-4">` 包裹本组件。
 * 面板首次打开时落在容器几何中心；用户按住标题栏（不含关闭按钮）可自由拖拽偏移（默认 draggable=true）。
 *
 * 两种布局变体：
 *   center     — 居中浮层（默认），受 size 控制最大宽度，最大高度 85vh，支持标题栏拖拽
 *   fullscreen — 全屏弹窗，宽度撑满容器，高度 = 容器高度 - 24px，底部对齐，顶部圆角；
 *                外层须是 flex-col 定高容器（如 fixed inset-0），面板加 className="mt-auto" 停靠底部
 *
 * @prop {'center'|'fullscreen'} [layout='center'] — 布局变体
 * @prop {'sm'|'md'|'lg'} [size='md'] — 宽度档位（仅 layout='center' 生效）
 * @prop {boolean} [showFooterHint=false] — 是否显示底部提示
 * @prop {boolean} [draggable] — layout='center' 时是否允许拖拽标题栏在页面内自由移动，默认 true；fullscreen 忽略
 * @prop {string} [title='模态标题'] — 标题
 * @prop {string|null} [subtitle='模态副标题'] — 副标题，为 null 时不展示
 * @prop {string} [footerHint='提示信息'] — 底部提示文案
 * @prop {string} [cancelText='取消'] — 取消按钮文案
 * @prop {string} [confirmText='确定'] — 确定按钮文案
 * @prop {function} [onClose=null] — 关闭回调，传入才显示关闭按钮
 * @prop {function} [onCancel=null] — 取消回调，传入才显示取消按钮
 * @prop {function} [onConfirm=null] — 确定回调，传入才显示确定按钮
 * @prop {ReactNode} [footer=null] — 自定义底栏，传入则替换默认底栏；若底栏整体为空则自动保留 24px 底部留白
 * @prop {string} [bodyClassName=''] — 内容区附加类名
 * @prop {string} [className=''] — 附加类名
 * @prop {object} [style] — 内联样式
 */
export default function Modal({
  layout = 'center',
  size = 'md',
  title = '模态标题',
  subtitle = '模态副标题',
  children,
  showFooterHint = false,
  footerHint = '提示信息',
  cancelText = '取消',
  confirmText = '确定',
  onCancel,
  onConfirm,
  onClose,
  footer,
  draggable,
  bodyClassName = '',
  className = '',
  style,
}) {
  const uid = useId();
  const titleId = `${uid}-title`;
  const subtitleId = `${uid}-subtitle`;
  const dragStateRef = useRef(null);
  const [dragOffset, setDragOffset] = useState({ x: 0, y: 0 });

  const canDrag = layout === 'center' && (draggable ?? true);
  const sizeClass = layout === 'center' ? SIZE_CLASS[size] : '';

  useEffect(() => {
    if (!canDrag) setDragOffset({ x: 0, y: 0 });
  }, [canDrag, layout]);

  const handleHeaderPointerDown = useCallback((event) => {
    if (!canDrag || event.button !== 0) return;
    if (event.target.closest('button')) return;
    dragStateRef.current = {
      pointerId: event.pointerId,
      startX: event.clientX,
      startY: event.clientY,
      originX: dragOffset.x,
      originY: dragOffset.y,
    };
    event.currentTarget.setPointerCapture(event.pointerId);
    event.preventDefault();
  }, [canDrag, dragOffset.x, dragOffset.y]);

  const handleHeaderPointerMove = useCallback((event) => {
    const dragState = dragStateRef.current;
    if (!dragState || dragState.pointerId !== event.pointerId) return;
    setDragOffset({
      x: dragState.originX + (event.clientX - dragState.startX),
      y: dragState.originY + (event.clientY - dragState.startY),
    });
  }, []);

  const handleHeaderPointerEnd = useCallback((event) => {
    const dragState = dragStateRef.current;
    if (!dragState || dragState.pointerId !== event.pointerId) return;
    dragStateRef.current = null;
    if (event.currentTarget.hasPointerCapture?.(event.pointerId)) {
      event.currentTarget.releasePointerCapture(event.pointerId);
    }
  }, []);

  const dragTransform = canDrag && (dragOffset.x !== 0 || dragOffset.y !== 0)
    ? `translate(${dragOffset.x}px, ${dragOffset.y}px)`
    : '';
  const panelStyle = {
    ...style,
    boxShadow: resolvePanelBoxShadow(layout, style?.boxShadow),
    transform: [dragTransform, style?.transform].filter(Boolean).join(' ') || undefined,
  };
  const hasDefaultFooterContent = Boolean((showFooterHint && footerHint) || onCancel || onConfirm);
  const shouldRenderCustomFooter = footer != null;
  const shouldRenderDefaultFooter = !shouldRenderCustomFooter && hasDefaultFooterContent;
  const shouldRenderBodyBottomGap = !shouldRenderCustomFooter && !hasDefaultFooterContent;

  return (
    <div
      className={[`tfds-modal`, [PANEL_BASE, LAYOUT_CLASS[layout], sizeClass, className].filter(Boolean).join(' ')].filter(Boolean).join(' ')}
      style={panelStyle}
      role="dialog"
      aria-modal="true"
      aria-labelledby={titleId}
      {...(subtitle ? { 'aria-describedby': subtitleId } : {})}
     data-tfds-component="Modal">
      <header
        className={[HEADER, canDrag ? HEADER_DRAGGABLE : ''].filter(Boolean).join(' ')}
        onPointerDown={canDrag ? handleHeaderPointerDown : undefined}
        onPointerMove={canDrag ? handleHeaderPointerMove : undefined}
        onPointerUp={canDrag ? handleHeaderPointerEnd : undefined}
        onPointerCancel={canDrag ? handleHeaderPointerEnd : undefined}
        data-tfds-region={canDrag ? 'modal-drag-handle' : undefined}
      >
        <div className="flex min-w-0 flex-1 flex-col items-start gap-0">
          <h2 id={titleId} className={TITLE}>
            {title}
          </h2>
          {subtitle ? (
            <p id={subtitleId} className={SUBTITLE}>
              {subtitle}
            </p>
          ) : null}
        </div>
        {onClose ? (
          <Button
            type="button"
            variant="ghost-black"
            size="sm"
            icon={<X size={16} strokeWidth={2} />}
            iconOnly
            onClick={onClose}
            tooltip="关闭"
            aria-label="关闭"
            className="shrink-0"
          />
        ) : null}
      </header>

      <div className={[BODY_CLASS[layout], bodyClassName].filter(Boolean).join(' ')}>{children}</div>

      {shouldRenderCustomFooter ? (
        <div className={FOOTER}>{footer}</div>
      ) : shouldRenderDefaultFooter ? (
        <footer className={FOOTER}>
          <div className={FOOTER_ROW}>
            {showFooterHint && footerHint ? (
              <p className={FOOTER_HINT}>{footerHint}</p>
            ) : (
              <span className="min-w-0 flex-1" />
            )}
            <div className={ACTIONS}>
              {onCancel ? (
                <Button type="button" variant="outline-black" size="md" onClick={onCancel}>
                  {cancelText}
                </Button>
              ) : null}
              {onConfirm ? (
                <Button type="button" variant="primary" size="md" onClick={onConfirm}>
                  {confirmText}
                </Button>
              ) : null}
            </div>
          </div>
        </footer>
      ) : (
        <div className={BODY_BOTTOM_GAP} aria-hidden="true" />
      )}
    </div>
  );
}
