import React, { useState, useRef, useEffect, useCallback } from 'react';
import { createPortal } from 'react-dom';

function useMediaQuery(query) {
  const [matches, setMatches] = useState(() => window.matchMedia(query).matches);
  useEffect(() => {
    const mql = window.matchMedia(query);
    const handler = (e) => setMatches(e.matches);
    mql.addEventListener('change', handler);
    return () => mql.removeEventListener('change', handler);
  }, [query]);
  return matches;
}

function formatTime(ms, showCentiseconds = true) {
  const minutes = Math.floor(ms / 60000);
  const seconds = Math.floor((ms % 60000) / 1000);
  if (!showCentiseconds) {
    return `${String(minutes).padStart(2, '0')}:${String(seconds).padStart(2, '0')}`;
  }
  const cs = Math.floor((ms % 1000) / 10);
  return `${String(minutes).padStart(2, '0')}:${String(seconds).padStart(2, '0')}:${String(cs).padStart(2, '0')}`;
}

const COUNTDOWN_PRESETS = [
  { label: '1:00', ms: 60000 },
  { label: '2:00', ms: 120000 },
  { label: '3:00', ms: 180000 },
  { label: '5:00', ms: 300000 },
];

export default function StopwatchWidget({ visible, onHide }) {
  const isDesktop = useMediaQuery('(min-width: 640px)');

  // Mode: 'stopwatch' | 'timer'
  const [mode, setMode] = useState('stopwatch');

  // Stopwatch state
  const [swRunning, setSwRunning] = useState(false);
  const [swElapsed, setSwElapsed] = useState(0);
  const [laps, setLaps] = useState([]);
  const swIntervalRef = useRef(null);
  const swStartRef = useRef(0);

  // Countdown state
  const [cdTarget, setCdTarget] = useState(60000);
  const [cdRemaining, setCdRemaining] = useState(60000);
  const [cdRunning, setCdRunning] = useState(false);
  const [cdExpired, setCdExpired] = useState(false);
  const [cdInputMin, setCdInputMin] = useState('1');
  const [cdInputSec, setCdInputSec] = useState('00');
  const cdIntervalRef = useRef(null);
  const cdStartRef = useRef(0);
  const cdRemainingAtStartRef = useRef(0);

  // Drag state (desktop only)
  const [position, setPosition] = useState({ x: window.innerWidth - 300, y: 80 });
  const [isDragging, setIsDragging] = useState(false);
  const dragOffset = useRef({ x: 0, y: 0 });
  const cardRef = useRef(null);

  // Stopwatch logic
  useEffect(() => {
    if (swRunning) {
      swStartRef.current = Date.now() - swElapsed;
      swIntervalRef.current = setInterval(() => {
        setSwElapsed(Date.now() - swStartRef.current);
      }, 10);
    } else {
      clearInterval(swIntervalRef.current);
    }
    return () => clearInterval(swIntervalRef.current);
  }, [swRunning]);

  const handleSwStartStop = () => setSwRunning(r => !r);
  const handleSwReset = () => {
    setSwRunning(false);
    setSwElapsed(0);
    setLaps([]);
  };
  const handleSwLap = () => {
    setLaps(prev => [...prev, swElapsed]);
  };

  // Countdown logic
  useEffect(() => {
    if (cdRunning) {
      cdStartRef.current = Date.now();
      cdRemainingAtStartRef.current = cdRemaining;
      cdIntervalRef.current = setInterval(() => {
        const elapsed = Date.now() - cdStartRef.current;
        const remaining = cdRemainingAtStartRef.current - elapsed;
        if (remaining <= 0) {
          setCdRemaining(0);
          setCdRunning(false);
          setCdExpired(true);
          clearInterval(cdIntervalRef.current);
        } else {
          setCdRemaining(remaining);
        }
      }, 10);
    } else {
      clearInterval(cdIntervalRef.current);
    }
    return () => clearInterval(cdIntervalRef.current);
  }, [cdRunning]);

  const handleCdStartPause = () => {
    if (cdExpired) return;
    setCdRunning(r => !r);
  };
  const handleCdReset = () => {
    setCdRunning(false);
    setCdRemaining(cdTarget);
    setCdExpired(false);
  };
  const handleCdPreset = (ms) => {
    setCdRunning(false);
    setCdTarget(ms);
    setCdRemaining(ms);
    setCdExpired(false);
    setCdInputMin(String(Math.floor(ms / 60000)));
    setCdInputSec(String(Math.floor((ms % 60000) / 1000)).padStart(2, '0'));
  };
  const handleCdCustomSet = () => {
    const min = parseInt(cdInputMin) || 0;
    const sec = parseInt(cdInputSec) || 0;
    const ms = (min * 60 + sec) * 1000;
    if (ms > 0) {
      setCdTarget(ms);
      setCdRemaining(ms);
      setCdRunning(false);
      setCdExpired(false);
    }
  };

  // Expired flash effect
  useEffect(() => {
    if (cdExpired) {
      const timeout = setTimeout(() => setCdExpired(false), 3000);
      return () => clearTimeout(timeout);
    }
  }, [cdExpired]);

  // Drag handlers (desktop)
  const handleDragStart = useCallback((e) => {
    if (!isDesktop) return;
    const clientX = e.touches ? e.touches[0].clientX : e.clientX;
    const clientY = e.touches ? e.touches[0].clientY : e.clientY;
    dragOffset.current = { x: clientX - position.x, y: clientY - position.y };
    setIsDragging(true);
  }, [isDesktop, position]);

  useEffect(() => {
    if (!isDragging) return;
    const handleMove = (e) => {
      const clientX = e.touches ? e.touches[0].clientX : e.clientX;
      const clientY = e.touches ? e.touches[0].clientY : e.clientY;
      setPosition({
        x: Math.max(0, Math.min(window.innerWidth - 280, clientX - dragOffset.current.x)),
        y: Math.max(0, Math.min(window.innerHeight - 100, clientY - dragOffset.current.y)),
      });
    };
    const handleUp = () => setIsDragging(false);

    document.addEventListener('mousemove', handleMove);
    document.addEventListener('mouseup', handleUp);
    document.addEventListener('touchmove', handleMove);
    document.addEventListener('touchend', handleUp);
    return () => {
      document.removeEventListener('mousemove', handleMove);
      document.removeEventListener('mouseup', handleUp);
      document.removeEventListener('touchmove', handleMove);
      document.removeEventListener('touchend', handleUp);
    };
  }, [isDragging]);

  if (!visible) return null;

  const cardClasses = isDesktop
    ? 'fixed z-50 w-[280px] rounded-xl shadow-2xl'
    : 'fixed z-50 bottom-0 left-0 right-0 rounded-t-xl shadow-2xl';

  const cardStyle = isDesktop ? { left: position.x, top: position.y } : {};

  const borderColor = cdExpired
    ? 'border-red-500 animate-pulse'
    : 'border-gray-700 dark:border-gray-600';

  const content = (
    <div
      ref={cardRef}
      className={`${cardClasses} bg-gray-900 dark:bg-gray-950 border-2 ${borderColor} text-white select-none`}
      style={cardStyle}
    >
      {/* Drag handle / header */}
      <div
        className={`flex items-center justify-between px-3 py-2 ${isDesktop ? 'cursor-grab active:cursor-grabbing' : ''}`}
        onMouseDown={handleDragStart}
        onTouchStart={handleDragStart}
      >
        <div className="flex gap-1">
          <button
            onClick={() => setMode('stopwatch')}
            className={`px-2 py-1 text-xs rounded transition ${mode === 'stopwatch' ? 'bg-indigo-600 text-white' : 'bg-gray-700 text-gray-300 hover:bg-gray-600'}`}
          >
            Stopwatch
          </button>
          <button
            onClick={() => setMode('timer')}
            className={`px-2 py-1 text-xs rounded transition ${mode === 'timer' ? 'bg-indigo-600 text-white' : 'bg-gray-700 text-gray-300 hover:bg-gray-600'}`}
          >
            Timer
          </button>
        </div>
        <button
          onClick={onHide}
          className="w-7 h-7 sm:w-6 sm:h-6 flex items-center justify-center text-gray-400 hover:text-white hover:bg-gray-700 rounded transition"
          title="Hide"
        >
          ✕
        </button>
      </div>

      {/* Display */}
      <div className="px-3 pb-2">
        <div className="bg-black/40 rounded-lg px-4 py-3 sm:py-2 text-center mb-3">
          <span
            className={`font-mono tracking-wider ${isDesktop ? 'text-2xl' : 'text-3xl'} ${mode === 'timer' && cdRemaining < 10000 && cdRunning ? 'text-red-400' : 'text-green-400'}`}
            style={{ fontFamily: "'Courier New', monospace" }}
          >
            {mode === 'stopwatch'
              ? formatTime(swElapsed)
              : formatTime(cdRemaining, false)
            }
          </span>
        </div>

        {/* Controls */}
        {mode === 'stopwatch' ? (
          <div className="flex gap-2 mb-2">
            <button
              onClick={handleSwStartStop}
              className={`flex-1 py-2 sm:py-1.5 rounded text-sm font-semibold transition ${swRunning ? 'bg-red-600 hover:bg-red-700' : 'bg-green-600 hover:bg-green-700'}`}
            >
              {swRunning ? 'Stop' : 'Start'}
            </button>
            {swRunning && (
              <button
                onClick={handleSwLap}
                className="flex-1 py-2 sm:py-1.5 rounded text-sm font-semibold bg-blue-600 hover:bg-blue-700 transition"
              >
                Lap
              </button>
            )}
            <button
              onClick={handleSwReset}
              className="flex-1 py-2 sm:py-1.5 rounded text-sm font-semibold bg-gray-600 hover:bg-gray-700 transition"
            >
              Reset
            </button>
          </div>
        ) : (
          <>
            <div className="flex gap-2 mb-2">
              <button
                onClick={handleCdStartPause}
                disabled={cdExpired || cdRemaining <= 0}
                className={`flex-1 py-2 sm:py-1.5 rounded text-sm font-semibold transition disabled:opacity-50 ${cdRunning ? 'bg-yellow-600 hover:bg-yellow-700' : 'bg-green-600 hover:bg-green-700'}`}
              >
                {cdRunning ? 'Pause' : 'Start'}
              </button>
              <button
                onClick={handleCdReset}
                className="flex-1 py-2 sm:py-1.5 rounded text-sm font-semibold bg-gray-600 hover:bg-gray-700 transition"
              >
                Reset
              </button>
            </div>
            {!cdRunning && (
              <>
                <div className="flex gap-1 mb-2">
                  {COUNTDOWN_PRESETS.map(p => (
                    <button
                      key={p.ms}
                      onClick={() => handleCdPreset(p.ms)}
                      className={`flex-1 py-1 rounded text-xs font-medium transition ${cdTarget === p.ms ? 'bg-indigo-600' : 'bg-gray-700 hover:bg-gray-600'}`}
                    >
                      {p.label}
                    </button>
                  ))}
                </div>
                <div className="flex items-center gap-1 text-xs">
                  <input
                    type="number"
                    min="0"
                    max="99"
                    value={cdInputMin}
                    onChange={(e) => setCdInputMin(e.target.value)}
                    className="w-10 bg-gray-800 border border-gray-600 rounded px-1 py-0.5 text-center text-white"
                  />
                  <span className="text-gray-400">m</span>
                  <input
                    type="number"
                    min="0"
                    max="59"
                    value={cdInputSec}
                    onChange={(e) => setCdInputSec(e.target.value)}
                    className="w-10 bg-gray-800 border border-gray-600 rounded px-1 py-0.5 text-center text-white"
                  />
                  <span className="text-gray-400">s</span>
                  <button
                    onClick={handleCdCustomSet}
                    className="ml-1 px-2 py-0.5 bg-indigo-600 hover:bg-indigo-700 rounded text-xs font-medium transition"
                  >
                    Set
                  </button>
                </div>
              </>
            )}
          </>
        )}

        {/* Lap list (stopwatch mode) */}
        {mode === 'stopwatch' && laps.length > 0 && (
          <div className={`mt-2 border-t border-gray-700 pt-2 overflow-y-auto ${isDesktop ? 'max-h-32' : 'max-h-24'}`}>
            {laps.map((lapTime, i) => {
              const prev = i === 0 ? 0 : laps[i - 1];
              const delta = lapTime - prev;
              return (
                <div key={i} className="flex justify-between text-xs text-gray-300 py-0.5">
                  <span className="text-gray-500">#{i + 1}</span>
                  <span className="font-mono">{formatTime(delta)}</span>
                  <span className="font-mono text-gray-500">{formatTime(lapTime)}</span>
                </div>
              );
            })}
          </div>
        )}
      </div>
    </div>
  );

  return createPortal(content, document.body);
}
