import { useCallback, useEffect, useLayoutEffect, useRef, useState } from 'react';
import type { PointerEvent } from 'react';
import { useTranslation } from 'react-i18next';
import { CloseIcon } from '../ui/icons/CloseIcon';
import { TabButton } from '../ui/TabButton';

const MIN_VISIBLE_PANEL_HEIGHT_PX = 104;

function clampDragOffset(panel: HTMLElement | null, offset: number): number {
  const panelHeight = panel?.offsetHeight || window.innerHeight * 0.9;
  const maxOffset = Math.max(0, panelHeight - MIN_VISIBLE_PANEL_HEIGHT_PX);
  return Math.min(maxOffset, Math.max(0, offset));
}

interface MobileDrawerProps {
  onClose: () => void;
  renderArea: () => React.ReactNode;
  renderProperties: () => React.ReactNode;
  tab: 'area' | 'properties';
  onTabChange: (tab: 'area' | 'properties') => void;
  onPanelRectChange?: (rect: DOMRectReadOnly) => void;
}

export default function MobileDrawer({
  onClose,
  renderArea,
  renderProperties,
  tab,
  onTabChange,
  onPanelRectChange,
}: MobileDrawerProps) {
  const { t } = useTranslation();
  const panelRef = useRef<HTMLDivElement>(null);
  const dragStartYRef = useRef(0);
  const dragStartOffsetRef = useRef(0);
  const dragOffsetRef = useRef(0);
  const isDraggingRef = useRef(false);
  const [dragOffset, setDragOffset] = useState(0);
  const [isDragging, setIsDragging] = useState(false);

  useLayoutEffect(() => {
    const panel = panelRef.current;
    if (!panel || !onPanelRectChange) return;

    const reportRect = () => onPanelRectChange(panel.getBoundingClientRect());
    reportRect();

    const observer = new ResizeObserver(reportRect);
    observer.observe(panel);
    window.addEventListener('resize', reportRect);
    window.visualViewport?.addEventListener('resize', reportRect);

    return () => {
      observer.disconnect();
      window.removeEventListener('resize', reportRect);
      window.visualViewport?.removeEventListener('resize', reportRect);
    };
  }, [onPanelRectChange]);

  useLayoutEffect(() => {
    const panel = panelRef.current;
    if (!panel || !onPanelRectChange) return;

    onPanelRectChange(panel.getBoundingClientRect());
  }, [dragOffset, onPanelRectChange]);

  // Close on Escape
  useEffect(() => {
    const handler = (e: KeyboardEvent) => {
      if (e.key === 'Escape') onClose();
    };
    window.addEventListener('keydown', handler);
    return () => window.removeEventListener('keydown', handler);
  }, [onClose]);

  const handleDragStart = useCallback((event: PointerEvent<HTMLElement>) => {
    event.preventDefault();
    event.currentTarget.setPointerCapture(event.pointerId);
    dragStartYRef.current = event.clientY;
    dragStartOffsetRef.current = dragOffsetRef.current;
    isDraggingRef.current = true;
    setIsDragging(true);
  }, []);

  const handleDragMove = useCallback((event: PointerEvent<HTMLElement>) => {
    if (!isDraggingRef.current) return;

    const nextOffset = clampDragOffset(
      panelRef.current,
      dragStartOffsetRef.current + event.clientY - dragStartYRef.current
    );
    dragOffsetRef.current = nextOffset;
    setDragOffset(nextOffset);
  }, []);

  const handleDragEnd = useCallback(() => {
    if (!isDraggingRef.current) return;

    dragStartYRef.current = 0;
    dragStartOffsetRef.current = dragOffsetRef.current;
    isDraggingRef.current = false;
    setIsDragging(false);
  }, []);

  return (
    <div
      data-tutorial="right-pane"
      className="pointer-events-none fixed inset-0 z-50 flex flex-col"
    >
      <div className="h-[10%] shrink-0" aria-hidden="true" />

      {/* Panel — bottom 90% */}
      <div
        ref={panelRef}
        className="pointer-events-auto h-[90%] bg-white dark:bg-navy-950 rounded-t-2xl flex flex-col border-t border-x border-warm-300 ring-1 ring-navy-950/10 shadow-2xl shadow-navy-950/45 dark:border-navy-600 dark:ring-white/10 dark:shadow-black/60 overflow-hidden"
        style={{
          transform: dragOffset > 0 ? `translateY(${dragOffset}px)` : undefined,
          transition: isDragging ? undefined : 'transform 180ms ease',
          willChange: isDragging ? 'transform' : undefined,
        }}
      >
        <div className="relative shrink-0 px-4 py-2">
          <div
            className="absolute inset-x-0 top-1/2 z-10 h-11 -translate-y-1/2 touch-none"
            data-mobile-drawer-drag-handle
            onPointerDown={handleDragStart}
            onPointerMove={handleDragMove}
            onPointerUp={handleDragEnd}
            onPointerCancel={handleDragEnd}
          />
          <div
            className="pointer-events-none flex w-full items-center justify-center"
            role="presentation"
          >
            <span className="h-1.5 w-12 rounded-full bg-warm-300 dark:bg-navy-600" />
          </div>
        </div>

        {/* Tab bar + close */}
        <div className="flex border-b border-warm-200 dark:border-navy-700 text-sm shrink-0">
          <TabButton
            label={t('common.area')}
            isActive={tab === 'area'}
            onClick={() => onTabChange('area')}
          />
          <TabButton
            label={t('common.properties')}
            isActive={tab === 'properties'}
            onClick={() => onTabChange('properties')}
          />
          <button
            onClick={onClose}
            className="ml-auto flex items-center justify-center w-10 h-10 rounded-lg hover:bg-warm-100 dark:hover:bg-navy-800"
            aria-label={t('mobileDrawer.closeDrawer')}
          >
            <CloseIcon className="w-5 h-5 text-warm-500 dark:text-warm-400" />
          </button>
        </div>

        {/* Content */}
        <div className="flex-1 overflow-hidden">
          {tab === 'area' ? renderArea() : renderProperties()}
        </div>
      </div>
    </div>
  );
}
