import React, { useState, useEffect, useRef } from "react";
import { ArrowPathIcon, SpeakerWaveIcon } from "@heroicons/react/24/outline";
import Textfield from "../Textfeild/Textfeild";

interface CaptchaProps {
  onChange: (isValid: boolean) => void;
  captchaImage?: string;
  captchaKey?: string;
  onRefresh?: () => void;
}

const Captcha: React.FC<CaptchaProps> = ({
  onChange,
  captchaImage,
  onRefresh,
}) => {
  const [input, setInput] = useState("");
  const canvasRef = useRef<HTMLCanvasElement>(null);
  const [solution, setSolution] = useState<number | null>(null);

  useEffect(() => {
    if (solution !== null) {
      drawCaptcha();
    }
  }, [solution]);

  useEffect(() => {
    generateNewCaptcha();
  }, []);

  const getRandomInt = (min: number, max: number) => {
    min = Math.ceil(min);
    max = Math.floor(max);
    return Math.floor(Math.random() * (max - min)) + min;
  };

  const getRandomFloat = (min: number, max: number) => {
    return Math.random() * (max - min) + min;
  };

  const generateNewCaptcha = () => {
    const newSolution = getRandomInt(111111, 999999);
    setSolution(newSolution);
  };

  const drawCaptcha = () => {
    if (!canvasRef.current || solution === null) return;
    const canvas = canvasRef.current;
    const ctx = canvas.getContext("2d");
    if (!ctx) return;

    const { width, height } = canvas;
    ctx.clearRect(0, 0, width, height);

    const gradient = ctx.createLinearGradient(0, 0, width, height);
    const colors = ["#f0f4f8", "#e8f0f5", "#f5f5f5", "#fafafa", "#f0f0f0"];
    gradient.addColorStop(0, colors[getRandomInt(0, colors.length)]);
    gradient.addColorStop(1, colors[getRandomInt(0, colors.length)]);
    ctx.fillStyle = gradient;
    ctx.fillRect(0, 0, width, height);

    ctx.fillStyle = "rgba(0, 0, 0, 0.1)";
    for (let i = 0; i < 150; i++) {
      const x = getRandomInt(0, width);
      const y = getRandomInt(0, height);
      const size = getRandomInt(1, 3);
      ctx.beginPath();
      ctx.arc(x, y, size, 0, Math.PI * 2);
      ctx.fill();
    }

    ctx.strokeStyle = "rgba(150, 150, 150, 0.3)";
    ctx.lineWidth = 1;
    for (let i = 0; i < 8; i++) {
      ctx.beginPath();
      const startX = getRandomInt(0, width);
      const startY = getRandomInt(0, height);
      ctx.moveTo(startX, startY);

      for (let j = 0; j < 3; j++) {
        const cpX = getRandomInt(0, width);
        const cpY = getRandomInt(0, height);
        const endX = getRandomInt(0, width);
        const endY = getRandomInt(0, height);
        ctx.quadraticCurveTo(cpX, cpY, endX, endY);
      }
      ctx.stroke();
    }

    ctx.strokeStyle = "rgba(200, 200, 200, 0.4)";
    ctx.lineWidth = 1.5;
    for (let i = 0; i < 5; i++) {
      ctx.beginPath();
      const y = getRandomInt(0, height);
      ctx.moveTo(0, y);
      for (let x = 0; x < width; x += 5) {
        const waveY = y + Math.sin(x * 0.1 + i) * 6;
        ctx.lineTo(x, waveY);
      }
      ctx.stroke();
    }

    const solutionStr = solution.toString();
    const charWidth = width / (solutionStr.length + 1);
    const baseY = height / 2;
    const fonts = [
      "Arial",
      "Verdana",
      "Courier New",
      "Georgia",
      "Times New Roman",
    ];
    const colors_text = ["#1a1a1a", "#2d2d2d", "#1f2937", "#111827", "#0f172a"];

    solutionStr.split("").forEach((char, index) => {
      ctx.save();

      const rotation = getRandomFloat(-0.3, 0.3);
      const x = charWidth * (index + 1);
      const yOffset = getRandomInt(-6, 6);
      const fontSize = getRandomInt(28, 36);
      const fontFamily = fonts[getRandomInt(0, fonts.length)];

      ctx.translate(x, baseY + yOffset);
      ctx.rotate(rotation);

      ctx.shadowColor = "rgba(0, 0, 0, 0.3)";
      ctx.shadowBlur = 2;
      ctx.shadowOffsetX = 1;
      ctx.shadowOffsetY = 1;

      if (Math.random() > 0.5) {
        const charGradient = ctx.createLinearGradient(-15, -20, 15, 20);
        charGradient.addColorStop(
          0,
          colors_text[getRandomInt(0, colors_text.length)]
        );
        charGradient.addColorStop(
          1,
          colors_text[getRandomInt(0, colors_text.length)]
        );
        ctx.fillStyle = charGradient;
      } else {
        ctx.fillStyle = colors_text[getRandomInt(0, colors_text.length)];
      }

      ctx.font = `bold ${fontSize}px ${fontFamily}`;
      ctx.textAlign = "center";
      ctx.textBaseline = "middle";
      ctx.fillText(char, 0, 0);

      if (Math.random() > 0.6) {
        ctx.strokeStyle = "rgba(100, 100, 100, 0.3)";
        ctx.lineWidth = 0.5;
        ctx.strokeText(char, 0, 0);
      }

      ctx.restore();
    });

    ctx.globalAlpha = 0.15;
    for (let i = 0; i < 6; i++) {
      const shapeType = getRandomInt(0, 3);
      const x = getRandomInt(0, width);
      const y = getRandomInt(0, height);
      const size = getRandomInt(8, 20);

      ctx.fillStyle = `hsl(${getRandomInt(0, 360)}, 50%, 50%)`;

      if (shapeType === 0) {
        ctx.beginPath();
        ctx.arc(x, y, size, 0, Math.PI * 2);
        ctx.fill();
      } else if (shapeType === 1) {
        ctx.fillRect(x - size / 2, y - size / 2, size, size);
      } else {
        ctx.beginPath();
        ctx.moveTo(x, y - size / 2);
        ctx.lineTo(x - size / 2, y + size / 2);
        ctx.lineTo(x + size / 2, y + size / 2);
        ctx.closePath();
        ctx.fill();
      }
    }
    ctx.globalAlpha = 1.0;

    ctx.fillStyle = "rgba(0, 0, 0, 0.05)";
    for (let i = 0; i < 50; i++) {
      const x = getRandomInt(0, width);
      const y = getRandomInt(0, height);
      const size = getRandomInt(1, 2);
      ctx.fillRect(x, y, size, size);
    }
  };

  const refresh = () => {
    generateNewCaptcha();
    setInput("");
    if (onRefresh) {
      onRefresh();
    }
  };

  const playAudio = () => {
    if (solution === null) return;
    const audio = new SpeechSynthesisUtterance(
      solution.toString().split("").join(" ")
    );
    audio.rate = 0.25;
    window.speechSynthesis.speak(audio);
  };

  const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    const value = e.target.value;
    setInput(value);
    if (solution !== null) {
      onChange(value === solution.toString());
    }
  };

  if (captchaImage) {
    return (
      <div className="flex flex-col gap-2 w-full">
        <div className="flex items-center gap-2">
          <Textfield
            fullWidth
            placeholder="کد امنیتی"
            value={input}
            onChange={handleChange}
            isNumber
          />
          <button
            type="button"
            onClick={onRefresh}
            className="p-2 rounded-lg hover:bg-gray-200 dark:hover:bg-dark-600 transition"
          >
            <ArrowPathIcon className="h-5 w-5 text-gray-600 dark:text-gray-300" />
          </button>
          <div className="h-10 w-[180px] overflow-hidden rounded-lg border border-gray-300 dark:border-dark-600">
            <img
              className="w-full h-full object-cover"
              src={captchaImage}
              alt="captcha"
            />
          </div>
        </div>
      </div>
    );
  }

  return (
    <div className="flex flex-col gap-2 w-full items-center">
      <div className="flex items-center gap-2">
        <canvas
          ref={canvasRef}
          width={200}
          height={40}
          className="border border-gray-300 dark:border-dark-600 rounded-lg"
        />
        <button
          type="button"
          onClick={refresh}
          className="p-2 rounded-lg hover:bg-gray-200 dark:hover:bg-dark-600 transition"
          aria-label="get new captcha"
        >
          <ArrowPathIcon className="h-5 w-5 text-gray-600 dark:text-gray-300" />
        </button>
        <button
          type="button"
          onClick={playAudio}
          className="p-2 rounded-lg hover:bg-gray-200 dark:hover:bg-dark-600 transition"
          aria-label="play audio"
        >
          <SpeakerWaveIcon className="h-5 w-5 text-gray-600 dark:text-gray-300" />
        </button>
      </div>
      <Textfield
        fullWidth
        placeholder="کد امنیتی"
        value={input}
        onChange={handleChange}
        isNumber
      />
    </div>
  );
};

export default Captcha;
