import { useEffect, useRef, useState, useCallback } from 'react';
import AnimatedAvatar from './AnimatedAvatar';

interface Props {
  isSpeaking: boolean;
  isListening: boolean;
  outfit: string;
  accessory: string | null;
  onTalkToggle: () => void;
}

export default function KiraAvatar(props: Props) {
  const canvasRef = useRef<HTMLDivElement>(null);
  const appRef = useRef<any>(null);
  const modelRef = useRef<any>(null);
  const [live2dReady, setLive2dReady] = useState(false);
  const [loadError, setLoadError] = useState(false);
  const animFrameRef = useRef<number>(0);

  // Initialize Live2D
  useEffect(() => {
    let mounted = true;
    const canvasEl = canvasRef.current;
    if (!canvasEl) return;

    const init = async () => {
      try {
        // Check if model exists
        const resp = await fetch('/live2d/models/kira/kira.model3.json', { method: 'HEAD' });
        if (!resp.ok) {
          if (mounted) setLoadError(true);
          return;
        }

        // Load Cubism core script
        await loadScript('/live2d/cubism/live2dcubismcore.min.js');

        // Dynamic imports
        const { Application } = await import('pixi.js');
        const { Live2DModel } = await import('pixi-live2d-display/cubism4');

        // Create Pixi app
        const app = new Application({
          width: 220,
          height: 280,
          transparent: true,
          antialias: true,
          resolution: 2,
          backgroundAlpha: 0,
        });
        appRef.current = app;

        if (!mounted) {
          app.destroy(true);
          return;
        }

        // Append canvas
        canvasEl.appendChild(app.view as HTMLCanvasElement);

        // Load model
        const model = await Live2DModel.from('/live2d/models/kira/kira.model3.json', {
          autoInteract: false,
        });
        modelRef.current = model;

        // Scale and center
        const scale = Math.min(220 / model.width, 280 / model.height) * 0.85;
        model.scale.set(scale);
        model.anchor.set(0.5, 0.5);
        model.position.set(app.screen.width / 2, app.screen.height / 2 + 10);

        app.stage.addChild(model);
        if (mounted) setLive2dReady(true);

        // Start idle animation
        try {
          model.motion('Idle');
        } catch {
          // Some models may not have Idle motion
        }

        // Set default expression
        try {
          model.expression('Normal');
        } catch {
          // Expressions are optional
        }

      } catch (e) {
        console.warn('[Live2D] Failed to load:', e);
        if (mounted) setLoadError(true);
      }
    };

    init();

    return () => {
      mounted = false;
      cancelAnimationFrame(animFrameRef.current);
      if (appRef.current) {
        appRef.current.destroy(true, { children: true });
        appRef.current = null;
      }
      modelRef.current = null;
    };
  }, []);

  // Handle speaking → lip sync
  useEffect(() => {
    if (!modelRef.current || !live2dReady) return;

    const model = modelRef.current;
    const core = (window as any).Live2DCubismCore;

    if (props.isSpeaking) {
      // Animate mouth while speaking
      let mouthPhase = 0;
      const animateMouth = () => {
        mouthPhase += 0.15;
        const openness = 0.3 + Math.sin(mouthPhase) * 0.35;
        try {
          model.internalModel.coreModel.setParameterValueByIndex(
            findParameterIndex(model, 'PARAM_MOUTH_OPEN_Y'),
            openness,
          );
        } catch { /* ignore */ }
        animFrameRef.current = requestAnimationFrame(animateMouth);
      };
      animateMouth();
    } else {
      // Close mouth when not speaking
      cancelAnimationFrame(animFrameRef.current);
      try {
        model.internalModel.coreModel.setParameterValueByIndex(
          findParameterIndex(model, 'PARAM_MOUTH_OPEN_Y'),
          0,
        );
      } catch { /* ignore */ }
    }

    return () => cancelAnimationFrame(animFrameRef.current);
  }, [props.isSpeaking, live2dReady]);

  // Handle outfit changes
  useEffect(() => {
    if (!modelRef.current || !live2dReady) return;
    // Texture swapping for outfits would go here
    // For now, the outfit system works on the fallback avatar
  }, [props.outfit, live2dReady]);

  // Handle listening pulse effect
  useEffect(() => {
    if (!modelRef.current || !live2dReady) return;
    // Could add a glow/breathing effect when listening
  }, [props.isListening, live2dReady]);

  return (
    <div className="glass-card p-4 flex flex-col items-center" style={{ minHeight: 340 }}>
      {/* Live2D canvas */}
      <div
        ref={canvasRef}
        className={`relative ${live2dReady ? 'block' : 'hidden'}`}
        style={{ width: 220, height: 280 }}
      />

      {/* Animated SVG placeholder when Live2D isn't available */}
      {(!live2dReady || loadError) && (
        <div className={live2dReady ? 'hidden' : 'block'}>
          <AnimatedAvatar
            isSpeaking={props.isSpeaking}
            isListening={props.isListening}
            outfit={props.outfit}
            accessory={props.accessory}
            onTalkToggle={props.onTalkToggle}
          />
        </div>
      )}

      {/* Loading state */}
      {!live2dReady && !loadError && (
        <div className="flex flex-col items-center gap-2 py-8">
          <div className="w-8 h-8 border-3 border-kira-pink border-t-transparent rounded-full animate-spin" />
          <p className="text-[11px] text-kira-plum/40">loading Kira...</p>
        </div>
      )}

      {/* Status bar */}
      <div className="mt-2 flex items-center gap-3 text-xs text-kira-plum/40">
        <span className={`w-2 h-2 rounded-full ${props.isSpeaking ? 'bg-kira-pink animate-pulse' : props.isListening ? 'bg-red-400 animate-pulse' : 'bg-kira-mint'}`} />
        <span>
          {props.isSpeaking ? 'speaking...' : props.isListening ? 'listening...' : live2dReady ? 'here with you' : 'loading...'}
        </span>
      </div>

      {/* Name + outfit indicator */}
      <div className="flex gap-2 mt-0.5 text-[10px] text-kira-plum/30">
        <span>Kira</span>
        {live2dReady && <span>· Live2D</span>}
      </div>
    </div>
  );
}

/** Load a script tag dynamically */
function loadScript(src: string): Promise<void> {
  return new Promise((resolve, reject) => {
    // Check if already loaded
    if (document.querySelector(`script[src="${src}"]`)) {
      resolve();
      return;
    }
    const script = document.createElement('script');
    script.src = src;
    script.onload = () => resolve();
    script.onerror = () => reject(new Error(`Failed to load ${src}`));
    document.head.appendChild(script);
  });
}

/** Find a parameter index by name in the Live2D model */
function findParameterIndex(model: any, name: string): number {
  const parameters = model.internalModel.coreModel.getParameterIds();
  return parameters.indexOf(name);
}
