import React, { useMemo, useRef, useEffect, useState } from "react";
import { DepartmentCorrelationPoint } from "../../../models/DepartmentCorrelation";
import {
  WIDTH,
  HEIGHT,
  MARGIN,
  padDomain,
  distanceToPoint,
  extent,
  scaleLinear,
  DEPARTEMENTS
} from "./scatterplot.utils";
import * as d3 from 'd3';
import { scaleLinear as d3ScaleLinear } from 'd3-scale';

export type HoverPoint = {
  collectedVolume: number;
  communeCode: string;
  rate: number;
};

type Props = {
  series: Map<string, DepartmentCorrelationPoint[]>;
  raw: DepartmentCorrelationPoint[];
};

export const ScatterPlotChart: React.FC<Props> = ({
    series,
    raw,
}) => {
    const canvasRef = useRef<HTMLCanvasElement | null>(null);
    const [hover, setHover] = useState<HoverPoint | null>(null);

    const innerW = WIDTH - MARGIN.left - MARGIN.right;
    const innerH = HEIGHT - MARGIN.top - MARGIN.bottom;

    const rates = useMemo(() => raw.map((d) => d.rate), [raw]);
    const collectedVolumes = useMemo(() => raw.map((d) => d.collectedVolume), [raw]);

    const xDomain = useMemo(() => padDomain(extent(rates)), [rates]);
    const yDomain = useMemo(() => padDomain(extent(collectedVolumes)), [collectedVolumes]);

    console.log(yDomain);

    const xScale = useMemo(
      () => scaleLinear(xDomain, [MARGIN.left, MARGIN.left + innerW]),
      [xDomain, innerW]
    );
  
    const yScale = useMemo(
      () => scaleLinear(yDomain, [MARGIN.top + innerH, MARGIN.top]),
      [yDomain, innerH]
    );

    const xTicks = useMemo(() => {
      const [min, max] = xDomain;
      const count = 10;
      const step = (max - min) / (count - 1);
      return Array.from({ length: count }, (_, i) => min + i * step);
    }, [xDomain]);
  
    const yTicks = useMemo(() => {
      const [min, max] = yDomain;
      const count = 5;
      const step = (max - min) / (count - 1);
      return Array.from({ length: count }, (_, i) => min + i * step);
    }, [yDomain]);

    const drawChart = () => {
      const canvas = canvasRef.current;
      if (!canvas) return;
      const ctx = canvas.getContext("2d");
      if (!ctx) return;

      ctx.clearRect(0, 0, WIDTH, HEIGHT);
      ctx.font = "10px sans-serif";

      // Axes
      ctx.strokeStyle = "#333";
      ctx.lineWidth = 1;

      // X axis
      ctx.beginPath();
      ctx.moveTo(MARGIN.left, MARGIN.top + innerH);
      ctx.lineTo(MARGIN.left + innerW, MARGIN.top + innerH);
      ctx.stroke();
  
      // Y axis
      ctx.beginPath();
      ctx.moveTo(MARGIN.left, MARGIN.top);
      ctx.lineTo(MARGIN.left, MARGIN.top + innerH);
      ctx.stroke();

      // X ticks
      ctx.textAlign = "center";
      ctx.textBaseline = "top";
      ctx.fillStyle = "#333";
      xTicks.forEach((t) => {
        const x = xScale(t);
        const y = MARGIN.top + innerH;
        ctx.beginPath();
        ctx.moveTo(x, y);
        ctx.lineTo(x, y + 6);
        ctx.stroke();
        ctx.fillText(`${Math.round(t)}`, x, y + 8);
      });
  
      // Y ticks
      ctx.textAlign = "right";
      ctx.textBaseline = "middle";
      yTicks.forEach((t) => {
        const y = yScale(t);
        ctx.beginPath();
        ctx.moveTo(MARGIN.left - 6, y);
        ctx.lineTo(MARGIN.left, y);
        ctx.stroke();
  
        // Grid line
        ctx.strokeStyle = "#ddd";
        ctx.beginPath();
        ctx.moveTo(MARGIN.left, y);
        ctx.lineTo(MARGIN.left + innerW, y);
        ctx.stroke();
        ctx.strokeStyle = "#333";
  
        ctx.fillText(t.toFixed(1), MARGIN.left - 10, y);
      });

      // Points
      Array.from(series.entries()).forEach(([communeCode, pts]) => {
        ctx.beginPath();

        const x = xScale(pts[0].rate);
        const y = yScale(pts[0].collectedVolume);

        // Outer circle
        ctx.fillStyle = "#000";
        ctx.beginPath();
        ctx.arc(x, y, 6, 0, Math.PI * 2);
        ctx.fill();
  
        // Inner circle
        ctx.fillStyle = "#fff";
        ctx.beginPath();
        ctx.arc(x, y, 4, 0, Math.PI * 2);
        ctx.fill();
      });

      // Tooltip
      const activeHover = hover ? hover: null;

      if (activeHover) {
        const { collectedVolume, rate, communeCode } = activeHover;

        const x = xScale(rate);
        const y = yScale(collectedVolume);

        // Tooltip box
        const tooltipX = x + 10;
        const tooltipY = y - 40;
        ctx.fillStyle = "#333";
        ctx.globalAlpha = 0.8;
        ctx.fillRect(tooltipX, tooltipY, 240, 58);
        ctx.globalAlpha = 1;
  
        // Tooltip text
        ctx.fillStyle = "#fff";
        ctx.textAlign = "left";
        ctx.textBaseline = "top";
        ctx.font = "bold 12px sans-serif";
        ctx.fillText(communeCode, tooltipX + 8, tooltipY + 8);
        ctx.font = "12px sans-serif";
        ctx.fillText(`${rate.toFixed(2)}%`, tooltipX + 8, tooltipY + 24);
        ctx.fillText(`Volume collecté: ${collectedVolume.toFixed(2)}`, tooltipX + 8, tooltipY + 40);
      }
    };

    useEffect(() => {
      drawChart();
    }, [series, hover]);

    const handleMouseMove = (e: React.MouseEvent<HTMLCanvasElement, MouseEvent>) => {
      const canvas = canvasRef.current;
      if (!canvas) return;
  
      const rect = canvas.getBoundingClientRect();
      const mouseX = e.clientX - rect.left;
      const mouseY = e.clientY - rect.top;
  
      let best: HoverPoint | null = null;
      let bestDist = Infinity;
  
      for (const [communeCode, pts] of Array.from(series.entries())) {
        const p = pts[0];
        const d = distanceToPoint(
          mouseX,
          mouseY,
          xScale(p.rate),
          yScale(p.collectedVolume),
        );

        if (d < bestDist) {
          bestDist = d;
          best = {
            collectedVolume: p.collectedVolume,
            rate: p.rate,
            communeCode,
          };
        }
      }
  
      if (best && bestDist < 10) setHover(best);
      else setHover(null);
    };

    return (
      <div className="chart-wrapper">
        <canvas
          ref={canvasRef}
          width={WIDTH}
          height={HEIGHT}
          className="chart-canvas"
          onMouseMove={handleMouseMove}
          onMouseLeave={() => setHover(null)}
        />
      </div>
    );
};