import { useEffect, useRef, useState } from "react";
import type { AtmosphereState } from "../lib/atmosphereTypes";
import styles from "./AtmospherePanel.module.css";

type EffectKey = keyof AtmosphereState;

const EFFECTS: { key: EffectKey; emoji: string; label: string }[] = [
  { key: "fog",    emoji: "🌫",  label: "Fog"    },
  { key: "fire",   emoji: "🔥",  label: "Fire"   },
  { key: "rain",   emoji: "🌧",  label: "Rain"   },
  { key: "embers", emoji: "✨", label: "Embers" },
];

interface AtmospherePanelProps {
  atmosphere: AtmosphereState;
  onAtmosphereChange: (next: AtmosphereState) => void;
}

export default function AtmospherePanel({
  atmosphere,
  onAtmosphereChange,
}: AtmospherePanelProps) {
  const [open, setOpen] = useState(false);
  // Local slider values so the label updates while dragging without triggering remounts
  const [localIntensity, setLocalIntensity] = useState({
    fog:    atmosphere.fog.intensity,
    fire:   atmosphere.fire.intensity,
    rain:   atmosphere.rain.intensity,
    embers: atmosphere.embers.intensity,
  });
  const containerRef = useRef<HTMLDivElement>(null);

  // Close panel on outside click
  useEffect(() => {
    if (!open) return;
    function onMouseDown(e: MouseEvent) {
      if (containerRef.current && !containerRef.current.contains(e.target as Node)) {
        setOpen(false);
      }
    }
    document.addEventListener("mousedown", onMouseDown);
    return () => document.removeEventListener("mousedown", onMouseDown);
  }, [open]);

  // Sync local intensity when atmosphere changes from socket
  useEffect(() => {
    setLocalIntensity({
      fog:    atmosphere.fog.intensity,
      fire:   atmosphere.fire.intensity,
      rain:   atmosphere.rain.intensity,
      embers: atmosphere.embers.intensity,
    });
  }, [atmosphere]);

  const activeEmojis = EFFECTS
    .filter(({ key }) => atmosphere[key].active)
    .map(({ emoji }) => emoji)
    .join("");

  function toggleEffect(key: EffectKey) {
    onAtmosphereChange({
      ...atmosphere,
      [key]: { ...atmosphere[key], active: !atmosphere[key].active },
    });
  }

  function handleSliderChange(key: EffectKey, value: number) {
    // Update label only — no socket emit yet
    setLocalIntensity((prev) => ({ ...prev, [key]: value }));
  }

  function handleSliderCommit(key: EffectKey, value: number) {
    // Emit on mouse/touch release
    onAtmosphereChange({
      ...atmosphere,
      [key]: { ...atmosphere[key], intensity: value },
    });
  }

  return (
    <div className={styles.container} ref={containerRef}>
      <button
        className={`${styles.trigger} ${activeEmojis ? styles.triggerActive : ""}`}
        onClick={() => setOpen((o) => !o)}
        title="Atmosphere effects"
      >
        {activeEmojis || "🌫"} ▾
      </button>

      {open && (
        <div className={styles.panel}>
          <div className={styles.panelTitle}>Atmosphere</div>
          {EFFECTS.map(({ key, emoji, label }) => (
            <div key={key} className={styles.effectRow}>
              <div className={styles.effectTop}>
                <span className={styles.effectLabel}>{emoji} {label}</span>
                <button
                  className={`${styles.toggle} ${atmosphere[key].active ? styles.toggleOn : ""}`}
                  onClick={() => toggleEffect(key)}
                  aria-label={`Toggle ${label}`}
                />
              </div>
              <div
                className={`${styles.intensityRow} ${
                  atmosphere[key].active ? styles.intensityActive : ""
                }`}
              >
                <span className={styles.intensityLabel}>
                  {localIntensity[key]}%
                </span>
                <input
                  type="range"
                  min={0}
                  max={100}
                  value={localIntensity[key]}
                  disabled={!atmosphere[key].active}
                  className={styles.slider}
                  onChange={(e) =>
                    handleSliderChange(key, Number(e.target.value))
                  }
                  onMouseUp={(e) =>
                    handleSliderCommit(
                      key,
                      Number((e.target as HTMLInputElement).value),
                    )
                  }
                  onTouchEnd={(e) =>
                    handleSliderCommit(
                      key,
                      Number((e.currentTarget as HTMLInputElement).value),
                    )
                  }
                />
              </div>
            </div>
          ))}
        </div>
      )}
    </div>
  );
}
