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

interface Props {
  isSpeaking: boolean;
  isListening: boolean;
  outfit: string;
  accessory: string | null;
  onTalkToggle: () => void;
  /** The Live2D Kira model instance (from Live2DStage) */
  kiraModel: any;
  live2dReady: boolean;
  onExpressionChange?: (expr: string) => void;
}

type ExpressionName = 'Normal' | 'Smile' | 'Sad' | 'Angry' | 'Surprised' | 'Blushing';

const EXPRESSIONS: ExpressionName[] = ['Normal', 'Smile', 'Sad', 'Angry', 'Surprised', 'Blushing'];
const IDLE_EXPRESSIONS: ExpressionName[] = ['Normal', 'Smile', 'Blushing'];

// The Epsilon model registers expressions with the .exp3.json suffix
const EXPR_MAP: Record<ExpressionName, string> = {
  Normal: 'Normal.exp3.json',
  Smile: 'Smile.exp3.json',
  Sad: 'Sad.exp3.json',
  Angry: 'Angry.exp3.json',
  Surprised: 'Surprised.exp3.json',
  Blushing: 'Blushing.exp3.json',
};

export default function KiraAvatar(props: Props) {
  const lipSyncRef = useRef<number>(0);
  const idleExprRef = useRef<ReturnType<typeof setInterval> | null>(null);
  const [currentExpression, setCurrentExpression] = useState<ExpressionName>('Normal');

  // Idle expression cycling
  useEffect(() => {
    if (!props.kiraModel || !props.live2dReady) return;
    idleExprRef.current = setInterval(() => {
      if (props.isSpeaking) return;
      const expr = IDLE_EXPRESSIONS[Math.floor(Math.random() * IDLE_EXPRESSIONS.length)];
      try { props.kiraModel.expression(EXPR_MAP[expr]); } catch {}
      setCurrentExpression(expr);
    }, 8000 + Math.random() * 7000);
    return () => clearInterval(idleExprRef.current ?? undefined);
  }, [props.kiraModel, props.live2dReady, props.isSpeaking]);

  // Lip sync from TTS
  useEffect(() => {
    const model = props.kiraModel;
    if (!model || !props.live2dReady) return;
    cancelAnimationFrame(lipSyncRef.current);
    if (props.isSpeaking) {
      let phase = 0;
      const animate = () => {
        phase += 0.12;
        const openness = 0.25 + Math.sin(phase) * 0.35;
        try {
          model.internalModel.coreModel.setParameterValueByIndex(
            findParam(model, 'PARAM_MOUTH_OPEN_Y'), openness,
          );
        } catch {}
        lipSyncRef.current = requestAnimationFrame(animate);
      };
      animate();
    } else {
      try {
        model.internalModel.coreModel.setParameterValueByIndex(
          findParam(model, 'PARAM_MOUTH_OPEN_Y'), 0,
        );
      } catch {}
    }
    return () => cancelAnimationFrame(lipSyncRef.current);
  }, [props.isSpeaking, props.live2dReady, props.kiraModel]);

  const pulseStyle = `
    @keyframes listening-pulse {
      0%, 100% { box-shadow: 0 0 0 0 rgba(248, 113, 113, 0.4); }
      50% { box-shadow: 0 0 0 12px rgba(248, 113, 113, 0); }
    }
    .animate-listening-pulse {
      animation: listening-pulse 1.5s infinite;
    }
  `;

  return (
    <div className="flex flex-col items-center w-full h-full">
      <div className="relative w-full flex-1" style={{ minHeight: 250 }}>
        {/* SVG fallback (shows before Live2D is ready) */}
        {!props.live2dReady && (
          <div className="absolute inset-0 flex items-center justify-center">
            <AnimatedAvatar
              isSpeaking={props.isSpeaking}
              isListening={props.isListening}
              outfit={props.outfit}
              accessory={props.accessory}
              onTalkToggle={props.onTalkToggle}
            />
          </div>
        )}

        {/* Loading spinner */}
        {!props.live2dReady && (
          <div className="absolute inset-0 flex flex-col items-center justify-center gap-2">
            <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>
        )}

        {/* Expression buttons */}
        {props.live2dReady && (
          <>
            <div className="absolute top-1 left-0 right-0 flex gap-1 justify-center flex-wrap pointer-events-none">
              <div className="pointer-events-auto flex gap-1 flex-wrap justify-center">
                {EXPRESSIONS.map((expr) => (
                  <button
                    key={expr}
                    onClick={() => {
                      try { props.kiraModel?.expression(EXPR_MAP[expr]); setCurrentExpression(expr); props.onExpressionChange?.(expr); } catch {}
                    }}
                    className={`text-[9px] px-2 py-0.5 rounded-full font-medium transition-all ${
                      currentExpression === expr
                        ? 'bg-kira-pink text-white'
                        : 'bg-white/70 text-kira-plum/40 hover:text-kira-plum/70'
                    }`}
                  >
                    {expr}
                  </button>
                ))}
              </div>
            </div>

            {/* Talk button */}
            <div className="absolute bottom-2 left-0 right-0 flex justify-center pointer-events-none">
              <button
                onClick={props.onTalkToggle}
                className={`pointer-events-auto flex items-center gap-2 px-5 py-2 rounded-full text-sm font-bold transition-all shadow-lg ${
                  props.isListening
                    ? 'bg-red-400 text-white scale-105 animate-listening-pulse'
                    : 'bg-gradient-to-r from-kira-pink to-kira-lav text-white hover:shadow-xl hover:scale-105'
                }`}
              >
                <span className="text-base">{props.isListening ? '⏹️' : '🎤'}</span>
                {props.isListening ? 'Listening...' : 'Talk to Kira'}
              </button>
            </div>

            {/* Status */}
            <div className="absolute bottom-2 right-3 flex items-center gap-2 text-xs text-kira-plum/50 pointer-events-none">
              <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...'
                : 'here with you'}
              </span>
            </div>
          </>
        )}
      </div>

      <style>{pulseStyle}</style>
    </div>
  );
}

function findParam(model: any, name: string): number {
  try {
    return model.internalModel.coreModel.getParameterIds().indexOf(name);
  } catch { return 0; }
}
