import React, { useState, useRef, useCallback } from 'react';
import { motion, AnimatePresence } from 'framer-motion';
import { LineChart, Check, X, RotateCcw, Trophy, ArrowRight, HelpCircle } from 'lucide-react';

interface Punto {
  x: number;
  y: number;
  id: string;
}

interface ConstructorCurvasProps {
  ejercicioId: string;
  onComplete?: (puntuacion: number) => void;
}

type Nivel = 'demanda' | 'oferta' | 'equilibrio';
type TipoCurva = 'demanda' | 'oferta';

interface NivelConfig {
  tipo: Nivel;
  titulo: string;
  descripcion: string;
  tipoCurvaEsperada: TipoCurva | 'ambas';
  mensajeExito: string;
}

const niveles: NivelConfig[] = [
  {
    tipo: 'demanda',
    titulo: 'Nivel 1: Curva de Demanda',
    descripcion: 'La demanda tiene pendiente negativa (cuando el precio sube, la cantidad demandada baja). Coloca al menos 2 puntos y traza la línea.',
    tipoCurvaEsperada: 'demanda',
    mensajeExito: '¡Correcto! La curva de demanda tiene pendiente negativa.'
  },
  {
    tipo: 'oferta',
    titulo: 'Nivel 2: Curva de Oferta',
    descripcion: 'La oferta tiene pendiente positiva (cuando el precio sube, los productores quieren vender más). Coloca al menos 2 puntos.',
    tipoCurvaEsperada: 'oferta',
    mensajeExito: '¡Correcto! La curva de oferta tiene pendiente positiva.'
  },
  {
    tipo: 'equilibrio',
    titulo: 'Nivel 3: Equilibrio de Mercado',
    descripcion: 'Dibuja ambas curvas para encontrar el punto de equilibrio donde se cruzan.',
    tipoCurvaEsperada: 'ambas',
    mensajeExito: '¡Excelente! Has encontrado el equilibrio de mercado.'
  }
];

const GRID_SIZE = 300;
const PADDING = 40;
const MAX_PRECIO = 100;
const MAX_CANTIDAD = 100;

export const ConstructorCurvas: React.FC<ConstructorCurvasProps> = ({ onComplete, ejercicioId: _ejercicioId }) => {
  const [nivelActual, setNivelActual] = useState(0);
  const [puntosDemanda, setPuntosDemanda] = useState<Punto[]>([]);
  const [puntosOferta, setPuntosOferta] = useState<Punto[]>([]);
  const [modoActivo, setModoActivo] = useState<TipoCurva>('demanda');
  const [mensaje, setMensaje] = useState<string>('');
  const [showSuccess, setShowSuccess] = useState(false);
  const [score, setScore] = useState(0);
  const [_startTime] = useState(Date.now());
  const [, setPuntosDibujados] = useState<{ demanda: boolean; oferta: boolean }>({ demanda: false, oferta: false });
  
  const svgRef = useRef<SVGSVGElement>(null);
  const [draggedPoint, setDraggedPoint] = useState<string | null>(null);

  const nivel = niveles[nivelActual];

  const cartesianToSvg = useCallback((x: number, y: number) => {
    const svgX = PADDING + (x / MAX_CANTIDAD) * GRID_SIZE;
    const svgY = PADDING + GRID_SIZE - (y / MAX_PRECIO) * GRID_SIZE;
    return { x: svgX, y: svgY };
  }, []);

  const svgToCartesian = useCallback((svgX: number, svgY: number) => {
    const x = ((svgX - PADDING) / GRID_SIZE) * MAX_CANTIDAD;
    const y = ((PADDING + GRID_SIZE - svgY) / GRID_SIZE) * MAX_PRECIO;
    return { 
      x: Math.max(0, Math.min(MAX_CANTIDAD, Math.round(x))),
      y: Math.max(0, Math.min(MAX_PRECIO, Math.round(y)))
    };
  }, []);

  const handleSvgClick = (e: React.MouseEvent<SVGSVGElement>) => {
    if (draggedPoint || nivelActual === 2) return;
    
    const rect = svgRef.current?.getBoundingClientRect();
    if (!rect) return;

    const svgX = e.clientX - rect.left;
    const svgY = e.clientY - rect.top;
    const cartesian = svgToCartesian(svgX, svgY);

    if (nivelActual === 0 && puntosDemanda.length >= 4) {
      setMensaje('Máximo 4 puntos para la demanda');
      return;
    }
    if (nivelActual === 1 && puntosOferta.length >= 4) {
      setMensaje('Máximo 4 puntos para la oferta');
      return;
    }

    const newPoint: Punto = {
      x: cartesian.x,
      y: cartesian.y,
      id: `point-${Date.now()}-${Math.random()}`
    };

    if (modoActivo === 'demanda') {
      setPuntosDemanda(prev => [...prev, newPoint]);
    } else {
      setPuntosOferta(prev => [...prev, newPoint]);
    }
    setMensaje('');
  };

  const handlePointDrag = (pointId: string, _tipo: TipoCurva) => {
    setDraggedPoint(pointId);
  };

  const handlePointMove = (e: React.MouseEvent<SVGSVGElement>) => {
    if (!draggedPoint) return;

    const rect = svgRef.current?.getBoundingClientRect();
    if (!rect) return;

    const svgX = e.clientX - rect.left;
    const svgY = e.clientY - rect.top;
    const cartesian = svgToCartesian(svgX, svgY);

    const updatePoint = (puntos: Punto[]) => 
      puntos.map(p => p.id === draggedPoint ? { ...p, x: cartesian.x, y: cartesian.y } : p);

    if (puntosDemanda.some(p => p.id === draggedPoint)) {
      setPuntosDemanda(updatePoint);
    } else if (puntosOferta.some(p => p.id === draggedPoint)) {
      setPuntosOferta(updatePoint);
    }
  };

  const handlePointUp = () => {
    setDraggedPoint(null);
  };

  const calcularPendiente = (puntos: Punto[]): number | null => {
    if (puntos.length < 2) return null;
    const sorted = [...puntos].sort((a, b) => a.x - b.x);
    const first = sorted[0];
    const last = sorted[sorted.length - 1];
    if (last.x === first.x) return 0;
    return (last.y - first.y) / (last.x - first.x);
  };

  const validarCurva = () => {
    const puntos = modoActivo === 'demanda' ? puntosDemanda : puntosOferta;
    
    if (puntos.length < 2) {
      setMensaje('Necesitas al menos 2 puntos para trazar una curva');
      return;
    }

    const pendiente = calcularPendiente(puntos);
    if (pendiente === null) return;

    if (modoActivo === 'demanda') {
      if (pendiente >= 0) {
        setMensaje('La demanda debe tener pendiente negativa (bajar de izquierda a derecha)');
        return;
      }
      setPuntosDibujados(prev => ({ ...prev, demanda: true }));
    } else {
      if (pendiente <= 0) {
        setMensaje('La oferta debe tener pendiente positiva (subir de izquierda a derecha)');
        return;
      }
      setPuntosDibujados(prev => ({ ...prev, oferta: true }));
    }

    setMensaje('');
    setShowSuccess(true);
    setScore(prev => prev + 33);

    setTimeout(() => {
      if (nivelActual < 2) {
        setNivelActual(prev => prev + 1);
        setShowSuccess(false);
        setMensaje('');
        if (nivelActual === 0) setModoActivo('oferta');
      }
    }, 2000);
  };

  const validarEquilibrio = () => {
    if (puntosDemanda.length < 2 || puntosOferta.length < 2) {
      setMensaje('Necesitas trazar ambas curvas con al menos 2 puntos cada una');
      return;
    }

    setShowSuccess(true);
    setScore(100);

    setTimeout(() => {
      if (onComplete) {
        onComplete(100);
      }
    }, 2000);
  };

  const reiniciar = () => {
    setPuntosDemanda([]);
    setPuntosOferta([]);
    setNivelActual(0);
    setModoActivo('demanda');
    setMensaje('');
    setShowSuccess(false);
    setScore(0);
    setPuntosDibujados({ demanda: false, oferta: false });
  };

  const eliminarPunto = (id: string, tipo: TipoCurva) => {
    if (tipo === 'demanda') {
      setPuntosDemanda(prev => prev.filter(p => p.id !== id));
    } else {
      setPuntosOferta(prev => prev.filter(p => p.id !== id));
    }
  };

  const renderLineaCurva = (puntos: Punto[], color: string) => {
    if (puntos.length < 2) return null;
    const sorted = [...puntos].sort((a, b) => a.x - b.x);
    const points = sorted.map(p => {
      const svg = cartesianToSvg(p.x, p.y);
      return `${svg.x},${svg.y}`;
    }).join(' ');

    return (
      <polyline
        points={points}
        fill="none"
        stroke={color}
        strokeWidth="3"
        strokeLinecap="round"
        strokeLinejoin="round"
      />
    );
  };

  return (
    <div className="w-full max-w-4xl mx-auto p-6 bg-white rounded-xl shadow-lg">
      <div className="mb-6">
        <div className="flex items-center justify-between mb-4">
          <div className="flex items-center gap-3">
            <LineChart className="w-8 h-8 text-blue-600" />
            <h2 className="text-2xl font-bold text-gray-800">{nivel.titulo}</h2>
          </div>
          <div className="flex items-center gap-4">
            <span className="text-sm text-gray-500">Nivel {nivelActual + 1} de 3</span>
            <div className="w-32 h-2 bg-gray-200 rounded-full overflow-hidden">
              <motion.div
                className="h-full bg-blue-600"
                initial={{ width: 0 }}
                animate={{ width: `${score}%` }}
              />
            </div>
            <button
              onClick={reiniciar}
              className="p-2 text-gray-500 hover:text-blue-600 transition-colors"
            >
              <RotateCcw className="w-5 h-5" />
            </button>
          </div>
        </div>
        <p className="text-gray-600">{nivel.descripcion}</p>
      </div>

      {nivelActual === 2 && (
        <div className="mb-4 p-3 bg-blue-50 rounded-lg flex items-center gap-2">
          <HelpCircle className="w-5 h-5 text-blue-600" />
          <span className="text-sm text-blue-700">
            Nivel Avanzado: Dibuja ambas curvas. La demanda (azul) con pendiente negativa, 
            y la oferta (verde) con pendiente positiva.
          </span>
        </div>
      )}

      <div className="flex flex-col md:flex-row gap-6">
        <div className="flex-1">
          <svg
            ref={svgRef}
            width={GRID_SIZE + 2 * PADDING}
            height={GRID_SIZE + 2 * PADDING}
            className="border-2 border-gray-300 rounded-lg bg-white cursor-crosshair"
            onClick={handleSvgClick}
            onMouseMove={handlePointMove}
            onMouseUp={handlePointUp}
            onMouseLeave={handlePointUp}
          >
            {/* Grid */}
            {Array.from({ length: 11 }).map((_, i) => (
              <g key={i}>
                <line
                  x1={PADDING + (i * GRID_SIZE) / 10}
                  y1={PADDING}
                  x2={PADDING + (i * GRID_SIZE) / 10}
                  y2={PADDING + GRID_SIZE}
                  stroke="#e5e7eb"
                  strokeWidth="1"
                />
                <line
                  x1={PADDING}
                  y1={PADDING + (i * GRID_SIZE) / 10}
                  x2={PADDING + GRID_SIZE}
                  y2={PADDING + (i * GRID_SIZE) / 10}
                  stroke="#e5e7eb"
                  strokeWidth="1"
                />
              </g>
            ))}

            {/* Ejes */}
            <line
              x1={PADDING}
              y1={PADDING + GRID_SIZE}
              x2={PADDING + GRID_SIZE}
              y2={PADDING + GRID_SIZE}
              stroke="#374151"
              strokeWidth="2"
            />
            <line
              x1={PADDING}
              y1={PADDING}
              x2={PADDING}
              y2={PADDING + GRID_SIZE}
              stroke="#374151"
              strokeWidth="2"
            />

            {/* Labels ejes */}
            <text x={PADDING + GRID_SIZE / 2} y={PADDING + GRID_SIZE + 25} textAnchor="middle" className="text-sm fill-gray-600">
              Cantidad
            </text>
            <text x={15} y={PADDING + GRID_SIZE / 2} textAnchor="middle" transform={`rotate(-90, 15, ${PADDING + GRID_SIZE / 2})`} className="text-sm fill-gray-600">
              Precio
            </text>

            {/* Curvas */}
            {(nivelActual === 0 || nivelActual === 2) && renderLineaCurva(puntosDemanda, '#3b82f6')}
            {(nivelActual === 1 || nivelActual === 2) && renderLineaCurva(puntosOferta, '#22c55e')}

            {/* Puntos Demanda */}
            {(nivelActual === 0 || nivelActual === 2) && puntosDemanda.map(punto => {
              const svg = cartesianToSvg(punto.x, punto.y);
              return (
                <motion.g key={punto.id}>
                  <circle
                    cx={svg.x}
                    cy={svg.y}
                    r="8"
                    fill="#3b82f6"
                    stroke="white"
                    strokeWidth="2"
                    className="cursor-move hover:r-10"
                    onMouseDown={() => handlePointDrag(punto.id, 'demanda')}
                    onClick={(e) => {
                      e.stopPropagation();
                      eliminarPunto(punto.id, 'demanda');
                    }}
                  />
                  <text x={svg.x} y={svg.y - 12} textAnchor="middle" className="text-xs fill-gray-500">
                    ({punto.x}, {punto.y})
                  </text>
                </motion.g>
              );
            })}

            {/* Puntos Oferta */}
            {(nivelActual === 1 || nivelActual === 2) && puntosOferta.map(punto => {
              const svg = cartesianToSvg(punto.x, punto.y);
              return (
                <motion.g key={punto.id}>
                  <circle
                    cx={svg.x}
                    cy={svg.y}
                    r="8"
                    fill="#22c55e"
                    stroke="white"
                    strokeWidth="2"
                    className="cursor-move"
                    onMouseDown={() => handlePointDrag(punto.id, 'oferta')}
                    onClick={(e) => {
                      e.stopPropagation();
                      eliminarPunto(punto.id, 'oferta');
                    }}
                  />
                  <text x={svg.x} y={svg.y - 12} textAnchor="middle" className="text-xs fill-gray-500">
                    ({punto.x}, {punto.y})
                  </text>
                </motion.g>
              );
            })}
          </svg>
        </div>

        <div className="w-full md:w-64 space-y-4">
          {nivelActual === 2 && (
            <div className="flex gap-2 p-3 bg-gray-100 rounded-lg">
              <button
                onClick={() => setModoActivo('demanda')}
                className={`flex-1 py-2 px-3 rounded text-sm font-medium transition-colors ${
                  modoActivo === 'demanda' 
                    ? 'bg-blue-600 text-white' 
                    : 'bg-white text-gray-700 hover:bg-gray-50'
                }`}
              >
                Demanda
              </button>
              <button
                onClick={() => setModoActivo('oferta')}
                className={`flex-1 py-2 px-3 rounded text-sm font-medium transition-colors ${
                  modoActivo === 'oferta' 
                    ? 'bg-green-600 text-white' 
                    : 'bg-white text-gray-700 hover:bg-gray-50'
                }`}
              >
                Oferta
              </button>
            </div>
          )}

          <div className="p-4 bg-gray-50 rounded-lg">
            <h3 className="font-semibold text-gray-700 mb-2">Puntos colocados:</h3>
            {modoActivo === 'demanda' || nivelActual === 2 ? (
              <div className="mb-2">
                <span className="text-sm text-blue-600 font-medium">Demanda: </span>
                <span className="text-sm text-gray-600">{puntosDemanda.length} puntos</span>
              </div>
            ) : null}
            {(modoActivo === 'oferta' || nivelActual === 2) && (
              <div>
                <span className="text-sm text-green-600 font-medium">Oferta: </span>
                <span className="text-sm text-gray-600">{puntosOferta.length} puntos</span>
              </div>
            )}
          </div>

          {mensaje && (
            <motion.div
              initial={{ opacity: 0, y: -10 }}
              animate={{ opacity: 1, y: 0 }}
              className="p-3 bg-red-50 border border-red-200 rounded-lg flex items-start gap-2"
            >
              <X className="w-5 h-5 text-red-500 flex-shrink-0 mt-0.5" />
              <p className="text-sm text-red-700">{mensaje}</p>
            </motion.div>
          )}

          {nivelActual < 2 ? (
            <button
              onClick={validarCurva}
              disabled={showSuccess}
              className="w-full py-3 px-4 bg-blue-600 text-white rounded-lg font-medium hover:bg-blue-700 disabled:opacity-50 transition-colors flex items-center justify-center gap-2"
            >
              <Check className="w-5 h-5" />
              Validar Curva
            </button>
          ) : (
            <button
              onClick={validarEquilibrio}
              disabled={showSuccess}
              className="w-full py-3 px-4 bg-purple-600 text-white rounded-lg font-medium hover:bg-purple-700 disabled:opacity-50 transition-colors flex items-center justify-center gap-2"
            >
              <Check className="w-5 h-5" />
              Validar Equilibrio
            </button>
          )}

          <AnimatePresence>
            {showSuccess && (
              <motion.div
                initial={{ opacity: 0, scale: 0.9 }}
                animate={{ opacity: 1, scale: 1 }}
                exit={{ opacity: 0, scale: 0.9 }}
                className="p-4 bg-green-50 border border-green-200 rounded-lg text-center"
              >
                <Trophy className="w-8 h-8 text-green-500 mx-auto mb-2" />
                <p className="font-semibold text-green-700">{nivel.mensajeExito}</p>
                {nivelActual === 2 && (
                  <div className="mt-3 flex items-center justify-center gap-2 text-green-600">
                    <span>Completado</span>
                    <ArrowRight className="w-4 h-4" />
                  </div>
                )}
              </motion.div>
            )}
          </AnimatePresence>
        </div>
      </div>
    </div>
  );
};

export default ConstructorCurvas;
