import { jsx, jsxs } from 'react/jsx-runtime';
import { useRef, useMemo, useEffect } from 'react';
import { Canvas, useFrame } from '@react-three/fiber';
import { Color, OneFactor, ZeroFactor, AddEquation, CustomBlending, BackSide } from 'three';
import { waveFragment, waveVertex, dotSphereFragment, dotSphereVertex, glowFragment, glowVertex } from './DotSphere.shaders.js';
import { useOrbState } from '../../hooks/useOrbState.js';

const STATE_CONFIG = {
    idle: { speed: 0.3, glowIntensity: 0.6, rimIntensity: 1.0 },
    listening: { speed: 0.6, glowIntensity: 1.0, rimIntensity: 1.5 },
    thinking: { speed: 1.2, glowIntensity: 1.4, rimIntensity: 2.0 },
    speaking: { speed: 0.8, glowIntensity: 1.2, rimIntensity: 1.8 },
};
const OrbScene = ({ colors, speed, gridDensity, dotSize, rimIntensity, glowIntensity, glowSize, state, }) => {
    const groupRef = useRef(null);
    const dotMatRef = useRef(null);
    const innerGlowRef = useRef(null);
    const outerGlowRef = useRef(null);
    const waveDeepRef = useRef(null);
    const waveSurfaceRef = useRef(null);
    // Colour objects (rebuilt only when hex strings change)
    const [c1, c2, c3] = colors;
    const colorObjs = useMemo(() => ({
        c1: new Color(c1),
        c2: new Color(c2),
        c3: new Color(c3),
    }), [c1, c2, c3]);
    // ── Uniforms – created once, mutated in useFrame / useEffect ──────────
    const dotUniforms = useMemo(() => ({
        u_time: { value: 0 },
        u_color1: { value: colorObjs.c1.clone() },
        u_color2: { value: colorObjs.c2.clone() },
        u_color3: { value: colorObjs.c3.clone() },
        u_dotSize: { value: dotSize },
        u_gridDensity: { value: gridDensity },
        u_rimIntensity: { value: rimIntensity },
    }), 
    // eslint-disable-next-line react-hooks/exhaustive-deps
    []);
    const innerGlowUniforms = useMemo(() => ({
        u_time: { value: 0 },
        u_color1: { value: colorObjs.c1.clone() },
        u_color2: { value: colorObjs.c2.clone() },
        u_color3: { value: colorObjs.c3.clone() },
        u_intensity: { value: glowIntensity * 0.8 },
        u_falloff: { value: 2.0 },
    }), 
    // eslint-disable-next-line react-hooks/exhaustive-deps
    []);
    const outerGlowUniforms = useMemo(() => ({
        u_time: { value: 0 },
        u_color1: { value: colorObjs.c1.clone() },
        u_color2: { value: colorObjs.c2.clone() },
        u_color3: { value: colorObjs.c3.clone() },
        u_intensity: { value: glowIntensity * 0.55 },
        u_falloff: { value: 1.0 },
    }), 
    // eslint-disable-next-line react-hooks/exhaustive-deps
    []);
    // Deep wave layer – large glowing blobs in the core
    const waveDeepUniforms = useMemo(() => ({
        u_time: { value: 0 },
        u_color1: { value: colorObjs.c1.clone() },
        u_color2: { value: colorObjs.c2.clone() },
        u_color3: { value: colorObjs.c3.clone() },
        u_intensity: { value: 1.2 },
        u_noiseScale: { value: 1.5 },
        u_flowSpeed: { value: 1.8 },
    }), 
    // eslint-disable-next-line react-hooks/exhaustive-deps
    []);
    // Surface wave layer – finer, faster glowing patterns near the shell
    const waveSurfaceUniforms = useMemo(() => ({
        u_time: { value: 0 },
        u_color1: { value: colorObjs.c1.clone() },
        u_color2: { value: colorObjs.c2.clone() },
        u_color3: { value: colorObjs.c3.clone() },
        u_intensity: { value: 0.9 },
        u_noiseScale: { value: 2.5 },
        u_flowSpeed: { value: 2.5 },
    }), 
    // eslint-disable-next-line react-hooks/exhaustive-deps
    []);
    // ── State-driven interpolation ─────────────────────────────────────────
    const stateProps = useMemo(() => ({ speed, glowIntensity, rimIntensity }), [speed, glowIntensity, rimIntensity]);
    const { valuesRef: stateRef, tick: stateTick } = useOrbState(state, STATE_CONFIG, stateProps);
    // ── Sync prop changes → uniforms ──────────────────────────────────────
    useEffect(() => {
        // Dot sphere
        if (dotMatRef.current) {
            const u = dotMatRef.current.uniforms;
            u.u_color1.value.copy(colorObjs.c1);
            u.u_color2.value.copy(colorObjs.c2);
            u.u_color3.value.copy(colorObjs.c3);
            u.u_dotSize.value = dotSize;
            u.u_gridDensity.value = gridDensity;
            u.u_rimIntensity.value = rimIntensity;
        }
        // Glow layers
        for (const ref of [innerGlowRef, outerGlowRef]) {
            if (ref.current) {
                ref.current.uniforms.u_color1.value.copy(colorObjs.c1);
                ref.current.uniforms.u_color2.value.copy(colorObjs.c2);
                ref.current.uniforms.u_color3.value.copy(colorObjs.c3);
            }
        }
        if (innerGlowRef.current)
            innerGlowRef.current.uniforms.u_intensity.value = glowIntensity * 0.8;
        if (outerGlowRef.current)
            outerGlowRef.current.uniforms.u_intensity.value = glowIntensity * 0.55;
        // Wave layers
        for (const ref of [waveDeepRef, waveSurfaceRef]) {
            if (ref.current) {
                ref.current.uniforms.u_color1.value.copy(colorObjs.c1);
                ref.current.uniforms.u_color2.value.copy(colorObjs.c2);
                ref.current.uniforms.u_color3.value.copy(colorObjs.c3);
            }
        }
    }, [colorObjs, dotSize, gridDensity, rimIntensity, glowIntensity]);
    // ── Animation loop ────────────────────────────────────────────────────
    useFrame(({ clock }, delta) => {
        // Tick state interpolation
        stateTick(delta);
        const sv = stateRef.current;
        const t = clock.getElapsedTime() * sv.speed;
        // Sync interpolated rimIntensity / glowIntensity into uniforms
        if (dotMatRef.current) {
            dotMatRef.current.uniforms.u_rimIntensity.value = sv.rimIntensity;
        }
        if (innerGlowRef.current) {
            innerGlowRef.current.uniforms.u_intensity.value = sv.glowIntensity * 0.8;
        }
        if (outerGlowRef.current) {
            outerGlowRef.current.uniforms.u_intensity.value = sv.glowIntensity * 0.55;
        }
        // Update time uniform on every material
        for (const ref of [
            dotMatRef,
            innerGlowRef,
            outerGlowRef,
            waveDeepRef,
            waveSurfaceRef,
        ]) {
            if (ref.current)
                ref.current.uniforms.u_time.value = t;
        }
        if (groupRef.current) {
            groupRef.current.rotation.y = clock.getElapsedTime() * 0.12;
        }
    });
    return (jsxs("group", { ref: groupRef, children: [jsxs("mesh", { scale: 0.85, children: [jsx("sphereGeometry", { args: [1, 48, 48] }), jsx("shaderMaterial", { ref: waveDeepRef, vertexShader: waveVertex, fragmentShader: waveFragment, uniforms: waveDeepUniforms, transparent: true, depthWrite: false })] }), jsxs("mesh", { scale: 0.96, children: [jsx("sphereGeometry", { args: [1, 48, 48] }), jsx("shaderMaterial", { ref: waveSurfaceRef, vertexShader: waveVertex, fragmentShader: waveFragment, uniforms: waveSurfaceUniforms, transparent: true, depthWrite: false })] }), jsxs("mesh", { children: [jsx("sphereGeometry", { args: [1, 64, 64] }), jsx("shaderMaterial", { ref: dotMatRef, vertexShader: dotSphereVertex, fragmentShader: dotSphereFragment, uniforms: dotUniforms, transparent: true, depthWrite: false })] }), jsxs("mesh", { scale: 1.12, children: [jsx("sphereGeometry", { args: [1, 32, 32] }), jsx("shaderMaterial", { ref: innerGlowRef, vertexShader: glowVertex, fragmentShader: glowFragment, uniforms: innerGlowUniforms, transparent: true, side: BackSide, blending: CustomBlending, blendEquation: AddEquation, blendSrc: OneFactor, blendDst: OneFactor, blendSrcAlpha: ZeroFactor, blendDstAlpha: OneFactor, depthWrite: false })] }), jsxs("mesh", { scale: glowSize, children: [jsx("sphereGeometry", { args: [1, 32, 32] }), jsx("shaderMaterial", { ref: outerGlowRef, vertexShader: glowVertex, fragmentShader: glowFragment, uniforms: outerGlowUniforms, transparent: true, side: BackSide, blending: CustomBlending, blendEquation: AddEquation, blendSrc: OneFactor, blendDst: OneFactor, blendSrcAlpha: ZeroFactor, blendDstAlpha: OneFactor, depthWrite: false })] })] }));
};
// ── Public DotSphere variant ─────────────────────────────────────────────────
const DEFAULT_COLORS = ["#00d2ff", "#a855f7", "#f97316"];
const DotSphere = ({ colors = DEFAULT_COLORS, speed = 0.6, gridDensity = 40, dotSize = 0.055, rimIntensity = 1.5, glowIntensity = 1.0, glowSize = 1.5, state, }) => {
    return (jsx(Canvas, { className: "!absolute inset-0 w-full h-full", style: {
            filter: [
                'drop-shadow(0 0 10px rgba(168, 85, 247, 0.7))',
                'drop-shadow(0 0 25px rgba(147, 51, 234, 0.35))',
                'drop-shadow(0 0 50px rgba(124, 58, 237, 0.15))',
            ].join(' '),
        }, dpr: [1, 2], camera: { position: [0, 0, 3], fov: 50 }, gl: { antialias: true, alpha: true, premultipliedAlpha: false }, onCreated: ({ gl }) => {
            gl.setClearColor(0x000000, 0);
        }, children: jsx(OrbScene, { colors: colors, speed: speed, gridDensity: gridDensity, dotSize: dotSize, rimIntensity: rimIntensity, glowIntensity: glowIntensity, glowSize: glowSize, state: state }) }));
};

export { DotSphere };
