"use client";

/**
 * Hero'daki (TurkeyPixelMap) imleç ısı fırçasının ortak hook hali.
 * `data-px` işaretli rect'ler imleç yaklaşınca anında turuncuya ısınır,
 * uzaklaşınca yavaşça kendi rengine soğur (asimetrik zamanlama).
 *
 * SVG katmanları çoğunlukla pointer-events-none olduğundan imleç window
 * üzerinden izlenir ve viewBox koordinatına çevrilir. Beklenen veri
 * öznitelikleri: data-px, data-cx, data-cy, data-op (taban opaklık).
 *
 * Landing'de 16 örnek yaşar: her örneğin kendi window dinleyicisi yerine
 * modül seviyesinde TEK pointermove dinleyicisi + rAF birleştirmesi kullanılır;
 * kare başına en fazla bir tarama yapılır, imleçten uzak örnekler hiç
 * piksel iterasyonuna girmez.
 */

import { useEffect, type RefObject } from "react";
import { animate, type AnimationPlaybackControls } from "motion";

const FINE_POINTER_QUERY = "(hover: hover) and (pointer: fine)";
const HOT_COLOR = "#f97316"; // orange-500
const HOT_OPACITY = 0.85;
const HEAT_DURATION = 0.15; // ısınma: anlık geri bildirim
const COOL_DURATION = 1.4; // soğuma: iz gibi yavaşça söner

type HeatTarget = {
  el: SVGRectElement;
  cx: number;
  cy: number;
  baseOpacity: number;
};

type HeatInstance = {
  svg: SVGSVGElement;
  viewW: number;
  radius: number;
  baseColor: string;
  pixels: HeatTarget[];
  hot: Set<SVGRectElement>;
  controls: Map<SVGRectElement, AnimationPlaybackControls>;
};

const instances = new Set<HeatInstance>();
let sonOlay: PointerEvent | null = null;
let rafId = 0;

function calistir(
  inst: HeatInstance,
  el: SVGRectElement,
  to: { fill: string; fillOpacity: number },
  duration: number,
) {
  inst.controls.get(el)?.stop();
  inst.controls.set(el, animate(el, to, { duration, ease: "easeOut" }));
}

function tara() {
  rafId = 0;
  const e = sonOlay;
  if (!e) return;
  for (const inst of instances) {
    const rect = inst.svg.getBoundingClientRect();
    if (rect.width === 0) continue;
    const scale = rect.width / inst.viewW;
    const pad = inst.radius * scale;
    // İmleç fırça menzilinin tamamen dışındaysa ve sıcak piksel yoksa
    // bu örnek için hiç hesap yapma
    if (
      inst.hot.size === 0 &&
      (e.clientX < rect.left - pad ||
        e.clientX > rect.right + pad ||
        e.clientY < rect.top - pad ||
        e.clientY > rect.bottom + pad)
    ) {
      continue;
    }
    const x = (e.clientX - rect.left) / scale;
    const y = (e.clientY - rect.top) / scale;
    for (const p of inst.pixels) {
      const d2 = (p.cx - x) ** 2 + (p.cy - y) ** 2;
      const isHot = d2 <= inst.radius * inst.radius;
      if (isHot && !inst.hot.has(p.el)) {
        inst.hot.add(p.el);
        calistir(
          inst,
          p.el,
          { fill: HOT_COLOR, fillOpacity: HOT_OPACITY },
          HEAT_DURATION,
        );
      } else if (!isHot && inst.hot.has(p.el)) {
        inst.hot.delete(p.el);
        calistir(
          inst,
          p.el,
          { fill: inst.baseColor, fillOpacity: p.baseOpacity },
          COOL_DURATION,
        );
      }
    }
  }
}

function onMove(e: PointerEvent) {
  sonOlay = e;
  if (!rafId) rafId = requestAnimationFrame(tara);
}

function kaydol(inst: HeatInstance) {
  if (instances.size === 0) {
    window.addEventListener("pointermove", onMove, { passive: true });
  }
  instances.add(inst);
}

function ayril(inst: HeatInstance) {
  instances.delete(inst);
  inst.controls.forEach((c) => c.stop());
  if (instances.size === 0) {
    window.removeEventListener("pointermove", onMove);
    if (rafId) cancelAnimationFrame(rafId);
    rafId = 0;
    sonOlay = null;
  }
}

export function usePixelHeat(
  svgRef: RefObject<SVGSVGElement | null>,
  {
    /** Fırça yarıçapı, SVG (viewBox) biriminde */
    radius = 34,
  }: { radius?: number } = {},
) {
  useEffect(() => {
    const svg = svgRef.current;
    if (!svg) return;
    // Dokunmatik cihazlarda hover yanlış tetiklenir; efekti imleçli cihazlara sakla
    if (!window.matchMedia(FINE_POINTER_QUERY).matches) return;

    const viewW = svg.viewBox.baseVal.width;
    if (!viewW) return;

    const pixels: HeatTarget[] = Array.from(
      svg.querySelectorAll<SVGRectElement>("[data-px]"),
    ).map((el) => ({
      el,
      cx: Number(el.dataset.cx),
      cy: Number(el.dataset.cy),
      baseOpacity: Number(el.dataset.op),
    }));
    if (pixels.length === 0) return;

    const inst: HeatInstance = {
      svg,
      viewW,
      radius,
      baseColor: getComputedStyle(svg).color,
      pixels,
      hot: new Set(),
      controls: new Map(),
    };
    kaydol(inst);
    return () => ayril(inst);
  }, [svgRef, radius]);
}
