import { useRef, useState, useEffect, useCallback } from "react";
import Player from "./player";
import Bomb from "./bomb";
import Grenade from "./grenade";
import PipBombTimer from "./PipBombTimer";
import Advisories from "./advisories";
import KillFeed from "./killfeed";
import { computeLetterboxRect } from "../utilities/pipUtils";
import { getRadarPosition } from "../utilities/utilities";
import { useAutozoom } from "../hooks/useAutozoom";
import { usePovLock } from "../hooks/usePovLock";

// ─── Dropped Weapon Icon ────────────────────────────────────────────────────────
const DROPPED_UTILITY_TYPES = new Set([
  "flashbang", "hegrenade", "smokegrenade",
  "molotov", "incgrenade", "decoy",
]);

const DroppedWeaponIcon = ({ weaponType, screenX, screenY, weaponKey, settings }) => {
  const isUtil = DROPPED_UTILITY_TYPES.has(weaponType);
  const sizeMult = isUtil
    ? (settings?.droppedUtilitySize ?? 1.0)
    : (settings?.droppedWeaponSize ?? 1.0);
  const iconSize = 18 * sizeMult;
  const itemOpacity = isUtil
    ? (settings?.droppedUtilityOpacity ?? 0.92)
    : (settings?.droppedWeaponOpacity ?? 0.92);
  const userColor = isUtil
    ? (settings?.droppedUtilityColor ?? "#94a3b8")
    : (settings?.droppedWeaponColor ?? "#94a3b8");
  const useCustomColor = userColor && userColor !== '#94a3b8';
  const iconUrl = `/assets/icons/${weaponType}.svg`;

  const containerBase = {
    width: iconSize, height: iconSize,
    left: screenX - iconSize / 2, top: screenY - iconSize / 2,
    position: 'absolute', zIndex: 120, opacity: itemOpacity,
  };

  // ── Custom color: use SVG as CSS mask on colored background ──
  if (useCustomColor) {
    return (
      <div key={weaponKey} className="absolute pointer-events-none" style={containerBase}>
        <div style={{
          width: '100%', height: '100%',
          backgroundColor: userColor,
          boxShadow: `0 0 5px ${userColor}`,
          WebkitMaskImage: `url(${iconUrl})`,
          maskImage: `url(${iconUrl})`,
          WebkitMaskSize: 'contain', maskSize: 'contain',
          WebkitMaskRepeat: 'no-repeat', maskRepeat: 'no-repeat',
          WebkitMaskPosition: 'center', maskPosition: 'center',
        }} />
      </div>
    );
  }

  // ── Default: show SVG, fallback to diamond on error ──
  const [svgError, setSvgError] = useState(false);

  if (svgError) {
    return (
      <div key={weaponKey} className="absolute pointer-events-none" style={{
        ...containerBase,
        borderRadius: 2, transform: 'rotate(45deg)',
        backgroundColor: '#94a3b8', boxShadow: '0 0 6px #94a3b8',
        filter: 'drop-shadow(0 1px 3px rgba(0,0,0,0.8))',
      }} />
    );
  }

  return (
    <div key={weaponKey} className="absolute pointer-events-none" style={{
      ...containerBase,
      filter: 'drop-shadow(0 1px 3px rgba(0,0,0,0.8))',
    }}>
      <img src={iconUrl} alt={weaponType}
        style={{ width: '100%', height: '100%', objectFit: 'contain' }}
        onError={() => setSvgError(true)} />
    </div>
  );
};

const MIN_ZOOM = 1.0;
const MAX_ZOOM = 4.0;
const ZOOM_FACTOR = 1.18;

const PipRadar = ({
  playerArray,
  mapData,
  bombData,
  grenadeArray = [],
  droppedWeaponArray = [],
  localTeam,
  averageLatency,
  settings,
  roundInfo,
  lockedPlayerIdx = null,
  followYourselfRotation = false,
}) => {
  const pipContainerRef = useRef();
  const pipImageRef = useRef();

  // Letterbox rect for PiP radar image — same shape as main radar's imgStyle
  const [pipImgStyle, setPipImgStyle] = useState({ w: 0, h: 0, ml: 0, mt: 0 });

  // Zoom & pan state (independent from main radar)
  const [pipZoom, setPipZoom] = useState(1);
  const [pipPan, setPipPan] = useState({ x: 0, y: 0 });

  // Manual zoom tracking (to pause autozoom when user scrolls)
  const manualZoomRef = useRef(false);
  const manualZoomTimeoutRef = useRef(null);
  const resetQueuesRef = useRef(null);

  // Drag state
  const dragRef = useRef(null);
  const touchRef = useRef(null);

  // POV Lock — rAF rotation
  const mapWrapperRef = useRef(null);
  const rotationRef   = useRef(0);
  const rafIdRef      = useRef(null);
  const playerArrayRef = useRef(playerArray);
  const mapDataRef     = useRef(mapData);
  playerArrayRef.current = playerArray;
  mapDataRef.current     = mapData;
  const [playerRotation, setPlayerRotation] = useState(0);

  // ── Measure letterbox rect — same logic as radar.jsx ──────────────────────
  const measurePip = useCallback(() => {
    const img = pipImageRef.current;
    const con = pipContainerRef.current;
    if (!img || !con) return;

    const nw = img.naturalWidth || 1024;
    const nh = img.naturalHeight || 1024;
    const cw = con.clientWidth;
    const ch = con.clientHeight;

    if (!cw || !ch) return;

    const rect = computeLetterboxRect(cw, ch, nw, nh);
    setPipImgStyle(rect);
  }, []);

  // ResizeObserver on PiP container — triggers when PiP window is resized
  // Also listen to the PiP window's resize event directly for OS-level resize
  useEffect(() => {
    const img = pipImageRef.current;
    const con = pipContainerRef.current;
    if (!img || !con) return;

    img.addEventListener("load", measurePip);

    // ResizeObserver on the container element
    const ro = new ResizeObserver(measurePip);
    ro.observe(con);

    // Also observe the window resize event (for documentPictureInPicture OS resize)
    const pipWin = con.ownerDocument?.defaultView;
    if (pipWin && pipWin !== window) {
      pipWin.addEventListener("resize", measurePip);
    }

    measurePip();

    return () => {
      img.removeEventListener("load", measurePip);
      ro.disconnect();
      if (pipWin && pipWin !== window) {
        pipWin.removeEventListener("resize", measurePip);
      }
    };
  }, [mapData?.name, measurePip]);

  // Reset zoom/pan when map changes
  useEffect(() => {
    setPipZoom(1);
    setPipPan({ x: 0, y: 0 });
    manualZoomRef.current = false;
    if (manualZoomTimeoutRef.current) clearTimeout(manualZoomTimeoutRef.current);
    resetQueuesRef.current?.();
  }, [mapData?.name]);

  // ── POV Lock hook ─────────────────────────────────────────────────────────
  const { isLocked, targetRot, cumulativeRotRef } = usePovLock({
    lockedPlayerIdx,
    playerArray,
    mapData,
    imgStyle: pipImgStyle,
    setZoom: setPipZoom,
    setPan: setPipPan,
    zoom: settings?.followZoom ?? 3.5,
  });

  // ── rAF rotation loop (mirrors radar.jsx) ─────────────────────────────────
  useEffect(() => {
    if (!isLocked) {
      if (rafIdRef.current) { cancelAnimationFrame(rafIdRef.current); rafIdRef.current = null; }
      rotationRef.current = 0;
      setPlayerRotation(0);
      if (mapWrapperRef.current)
        mapWrapperRef.current.style.transform = `translate(${pipPan.x}px, ${pipPan.y}px) scale(${pipZoom})`;
      return;
    }

    let frameCount = 0;
    const animate = () => {
      if (mapWrapperRef.current) {
        const doRotate = followYourselfRotation && isLocked && lockedPlayerIdx !== null;
        const target = doRotate ? targetRot + cumulativeRotRef.current : 0;
        let delta = target - rotationRef.current;
        while (delta >  180) delta -= 360;
        while (delta < -180) delta += 360;
        rotationRef.current += delta * 0.2;

        if (doRotate) {
          // Dynamic pan recalc — same as main radar
          const pa = playerArrayRef.current;
          const md = mapDataRef.current;
          const lockedPlayer = pa?.find(p => p.m_idx === lockedPlayerIdx && !p.m_is_dead);
          if (lockedPlayer && md) {
            const pos = getRadarPosition(md, lockedPlayer.m_position ?? lockedPlayer);
            if (pos) {
              const cw = pipContainerRef.current?.clientWidth || 512;
              const ch = pipContainerRef.current?.clientHeight || 512;
              const ml = pipImgStyle.ml ?? 0;
              const mt = pipImgStyle.mt ?? 0;
              const iw = pipImgStyle.w || 512;
              const ih = pipImgStyle.h || 512;
              const px = ml + iw * pos.x;
              const py = mt + ih * pos.y;
              const rx = (px - cw / 2) * pipZoom;
              const ry = (py - ch / 2) * pipZoom;
              const angleRad = rotationRef.current * Math.PI / 180;
              const c = Math.cos(angleRad);
              const s = Math.sin(angleRad);
              const rotX = rx * c - ry * s;
              const rotY = rx * s + ry * c;
              mapWrapperRef.current.style.transform =
                `translate(${-rotX}px, ${-rotY}px) scale(${pipZoom}) rotate(${rotationRef.current}deg)`;
            }
          }
        } else {
          mapWrapperRef.current.style.transform =
            `translate(${pipPan.x}px, ${pipPan.y}px) scale(${pipZoom}) rotate(${rotationRef.current}deg)`;
        }

        frameCount++;
        if (frameCount % 3 === 0) setPlayerRotation(rotationRef.current);
      }
      rafIdRef.current = requestAnimationFrame(animate);
    };

    rafIdRef.current = requestAnimationFrame(animate);
    return () => { if (rafIdRef.current) { cancelAnimationFrame(rafIdRef.current); rafIdRef.current = null; } };
  }, [isLocked, targetRot, pipPan.x, pipPan.y, pipZoom, cumulativeRotRef, followYourselfRotation, lockedPlayerIdx]);

  // ── Clamp pan — same logic as radar.jsx ───────────────────────────────────
  const clamp = useCallback((px, py, z) => {
    const con = pipContainerRef.current;
    if (!con || !pipImgStyle.w) return { x: px, y: py };
    const maxX = Math.max(0, (pipImgStyle.w * z - con.clientWidth) / 2);
    const maxY = Math.max(0, (pipImgStyle.h * z - con.clientHeight) / 2);
    return {
      x: Math.min(maxX, Math.max(-maxX, px)),
      y: Math.min(maxY, Math.max(-maxY, py)),
    };
  }, [pipImgStyle]);

  // Clamp pan when zoom or imgStyle changes
  useEffect(() => {
    setPipPan(prev => clamp(prev.x, prev.y, pipZoom));
  }, [pipZoom, pipImgStyle, clamp]);

  // ── Autozoom — disabled when POV locked ───────────────────────────────────
  const { resetQueues } = useAutozoom({
    enabled: settings?.autoZoom === true && !isLocked,
    playerArray,
    mapData,
    imgStyle: pipImgStyle,
    manualZoomRef,
    setZoom: setPipZoom,
    setPan: setPipPan,
    clamp,
    settings,
  });
  resetQueuesRef.current = resetQueues;

  // ── Scroll wheel zoom ──────────────────────────────────────────────────────
  const onWheel = useCallback((e) => {
    e.preventDefault();
    const con = pipContainerRef.current;
    if (!con) return;

    // Mark manual zoom — pause autozoom for 3s
    manualZoomRef.current = true;
    if (manualZoomTimeoutRef.current) clearTimeout(manualZoomTimeoutRef.current);
    manualZoomTimeoutRef.current = setTimeout(() => {
      manualZoomRef.current = false;
    }, 3000);

    const rect = con.getBoundingClientRect();
    const cx = e.clientX - (rect.left + rect.width / 2);
    const cy = e.clientY - (rect.top + rect.height / 2);

    setPipZoom(prev => {
      const next = e.deltaY < 0
        ? Math.min(MAX_ZOOM, prev * ZOOM_FACTOR)
        : Math.max(MIN_ZOOM, prev / ZOOM_FACTOR);
      const ratio = next / prev;

      setPipPan(prevPan => clamp(
        prevPan.x + (cx - prevPan.x) * (1 - ratio),
        prevPan.y + (cy - prevPan.y) * (1 - ratio),
        next
      ));
      return next;
    });
  }, [clamp]);

  useEffect(() => {
    const el = pipContainerRef.current;
    if (!el) return;
    el.addEventListener("wheel", onWheel, { passive: false });
    return () => el.removeEventListener("wheel", onWheel);
  }, [onWheel]);

  // ── Drag to pan (disabled when POV locked) ────────────────────────────────
  const onMouseDown = useCallback((e) => {
    if (isLocked) return;
    if (pipZoom <= 1 || e.button !== 0) return;
    e.preventDefault();
    dragRef.current = { mx: e.clientX, my: e.clientY, px: pipPan.x, py: pipPan.y };
  }, [pipZoom, pipPan]);

  const onMouseMove = useCallback((e) => {
    if (!dragRef.current) return;
    setPipPan(clamp(
      dragRef.current.px + (e.clientX - dragRef.current.mx),
      dragRef.current.py + (e.clientY - dragRef.current.my),
      pipZoom
    ));
  }, [pipZoom, clamp]);

  const onMouseUp = useCallback(() => {
    dragRef.current = null;
  }, []);

  // Touch events
  const onTouchStart = useCallback((e) => {
    if (pipZoom <= 1) return;
    touchRef.current = {
      tx: e.touches[0].clientX,
      ty: e.touches[0].clientY,
      px: pipPan.x,
      py: pipPan.y
    };
  }, [pipZoom, pipPan]);

  const onTouchMove = useCallback((e) => {
    if (!touchRef.current) return;
    e.preventDefault();
    setPipPan(clamp(
      touchRef.current.px + (e.touches[0].clientX - touchRef.current.tx),
      touchRef.current.py + (e.touches[0].clientY - touchRef.current.ty),
      pipZoom
    ));
  }, [pipZoom, clamp]);

  const onTouchEnd = useCallback(() => {
    touchRef.current = null;
  }, []);

  // ── Map transform — NOT used in JSX; rAF loop sets style.transform each frame
  // (same pattern as radar.jsx) to avoid React re-renders overriding rotation.
  const radarImage = mapData?.name ? `./data/${mapData.name}/radar.png` : null;

  return (
    <div
      ref={pipContainerRef}
      style={{
        width: "100%",
        height: "100%",
        position: "relative",
        overflow: "hidden",
        cursor: pipZoom > 1 ? (dragRef.current ? "grabbing" : "grab") : "default",
      }}
      onMouseDown={onMouseDown}
      onMouseMove={onMouseMove}
      onMouseUp={onMouseUp}
      onMouseLeave={onMouseUp}
      onTouchStart={onTouchStart}
      onTouchMove={onTouchMove}
      onTouchEnd={onTouchEnd}
    >
      {/* Map wrapper — fills container, transforms around centre (same as radar.jsx) */}
      {/* RAF loop owns the transform directly — no static transform in JSX */}
      <div
        ref={mapWrapperRef}
        style={{
          position: "absolute",
          inset: 0,
          transformOrigin: "50% 50%",
          willChange: "transform",
          pointerEvents: "none",
        }}
      >
        {/* Letterboxed map image — positioned at ml/mt inside wrapper */}
        {radarImage && (
          <img
            ref={pipImageRef}
            src={radarImage}
            alt="Radar Map"
            draggable={false}
            style={{
              position: "absolute",
              left: pipImgStyle.ml,
              top: pipImgStyle.mt,
              width: pipImgStyle.w || "100%",
              height: pipImgStyle.h || "100%",
              display: "block",
              userSelect: "none",
              opacity: settings?.mapOpacity ?? 1,
              filter: `brightness(${settings?.mapBrightness ?? 1}) contrast(${settings?.mapContrast ?? 1}) blur(${settings?.mapBlur ?? 0}px)`,
            }}
          />
        )}

        {/* Players — pass imgStyle (same shape as main radar) */}
        {playerArray.map(player => (
          <Player
            key={player.m_idx}
            playerData={player}
            mapData={mapData}
            localTeam={localTeam}
            averageLatency={averageLatency}
            settings={settings}
            mapRotation={isLocked ? playerRotation : 0}
            imgStyle={pipImgStyle}
            isFollowRotate={isLocked && followYourselfRotation}
            lockedPlayerIdx={lockedPlayerIdx}
          />
        ))}

        {/* Grenades */}
        {grenadeArray.map((grenade, i) => (
          <Grenade
            key={`gren-${i}`}
            grenadeData={grenade}
            mapData={mapData}
            imgSize={pipImgStyle}
            settings={settings}
          />
        ))}

        {/* ── Dropped weapons (weapon ESP) ── */}
        {(settings?.showDroppedWeapons !== false) && droppedWeaponArray.filter(weapon => {
          // Filter utilities vs weapons based on settings
          if (["flashbang","hegrenade","smokegrenade","molotov","incgrenade","decoy"].includes(weapon.type)) {
            return settings?.showDroppedUtilities !== false;
          }
          // Regular weapons: apply filter mode
          if (settings?.droppedWeaponFilterMode === "custom") {
            const filterList = settings?.droppedWeaponFilterList ?? [];
            return filterList.includes(weapon.type);
          }
          return true; // "all" mode
        }).map((weapon, i) => {
          const rp = getRadarPosition(mapData, { x: weapon.x, y: weapon.y });
          if (!rp) return null;
          return (
            <DroppedWeaponIcon
              key={`dw-${i}`}
              weaponType={weapon.type}
              screenX={(pipImgStyle.ml ?? 0) + (pipImgStyle.w || 0) * rp.x}
              screenY={(pipImgStyle.mt ?? 0) + (pipImgStyle.h || 0) * rp.y}
              weaponKey={`dw-${weapon.className}-${i}`}
              settings={settings}
            />
          );
        })}

        {/* Bomb — show only when dropped or planted (carried C4 already has badge on player dot) */}
        {bombData && bombData.state !== "carried" && (
          <Bomb
            bombData={bombData}
            mapData={mapData}
            imgSize={pipImgStyle}
            localTeam={localTeam}
            averageLatency={averageLatency}
            settings={settings}
          />
        )}
      </div>

      {/* Advisories overlay — top centre */}
      {settings?.showAdvisories !== false && (
        <Advisories
          playerArray={playerArray}
          bombData={bombData}
          roundInfo={roundInfo}
          settings={settings}
        />
      )}

      {/* KillFeed overlay — bottom right */}
      {settings?.showKillFeed !== false && (
        <div style={{
          position: "absolute",
          bottom: 36,
          right: 4,
          zIndex: 50,
          pointerEvents: "none",
        }}>
          <KillFeed playerArray={playerArray} />
        </div>
      )}

      {/* Map name label */}
      <div
        style={{
          position: "absolute",
          bottom: 32,
          left: 6,
          fontSize: 9,
          fontWeight: 700,
          color: "rgba(255,255,255,0.4)",
          textTransform: "uppercase",
          letterSpacing: "0.1em",
          pointerEvents: "none",
        }}
      >
        {mapData?.name}
      </div>

      {/* Zoom controls */}
      <div
        style={{
          position: "absolute",
          bottom: 6,
          right: 4,
          zIndex: 50,
          display: "flex",
          alignItems: "center",
          gap: 3,
        }}
        onMouseDown={e => e.stopPropagation()}
      >
        {pipZoom !== 1 && (
          <button
            onClick={() => {
              manualZoomRef.current = false;
              if (manualZoomTimeoutRef.current) clearTimeout(manualZoomTimeoutRef.current);
              setPipZoom(1);
              setPipPan({ x: 0, y: 0 });
              resetQueues();
            }}
            style={{
              padding: "3px 8px",
              fontSize: 10,
              fontWeight: 700,
              background: "rgba(0,0,0,0.65)",
              color: "#fff",
              border: "1px solid rgba(255,255,255,0.15)",
              borderRadius: 4,
              cursor: "pointer",
              fontFamily: "inherit",
              letterSpacing: "0.06em",
            }}
          >
            {Math.round(pipZoom * 100)}% ✕
          </button>
        )}
        <button
          onClick={() => {
            manualZoomRef.current = true;
            if (manualZoomTimeoutRef.current) clearTimeout(manualZoomTimeoutRef.current);
            manualZoomTimeoutRef.current = setTimeout(() => { manualZoomRef.current = false; }, 3000);
            setPipZoom(p => Math.max(MIN_ZOOM, +(p / ZOOM_FACTOR).toFixed(4)));
          }}
          style={{
            width: 22, height: 22, fontSize: 15, lineHeight: 1,
            background: "rgba(0,0,0,0.65)", color: "#fff",
            border: "1px solid rgba(255,255,255,0.15)", borderRadius: 4,
            cursor: "pointer", display: "flex", alignItems: "center", justifyContent: "center",
          }}
        >−</button>
        <button
          onClick={() => {
            manualZoomRef.current = true;
            if (manualZoomTimeoutRef.current) clearTimeout(manualZoomTimeoutRef.current);
            manualZoomTimeoutRef.current = setTimeout(() => { manualZoomRef.current = false; }, 3000);
            setPipZoom(p => Math.min(MAX_ZOOM, +(p * ZOOM_FACTOR).toFixed(4)));
          }}
          style={{
            width: 22, height: 22, fontSize: 15, lineHeight: 1,
            background: "rgba(0,0,0,0.65)", color: "#fff",
            border: "1px solid rgba(255,255,255,0.15)", borderRadius: 4,
            cursor: "pointer", display: "flex", alignItems: "center", justifyContent: "center",
          }}
        >+</button>
      </div>

      {/* Bomb timer bar — overlay at bottom */}
      {bombData && <PipBombTimer bombData={bombData} settings={settings} />}
    </div>
  );
};

export default PipRadar;
