import React, { useEffect, useRef, useState } from 'react';
import type { ModelViewerElement } from '@google/model-viewer';
import type { Locale } from './i18n';

declare module 'react' {
    namespace JSX {
        interface IntrinsicElements {
            'model-viewer': React.DetailedHTMLProps<React.HTMLAttributes<ModelViewerElement>, ModelViewerElement> & {
                src: string;
                alt: string;
                loading?: string;
                exposure?: string;
            };
        }
    }
}

const POSTER_SRC = '/assets/flameowl-poster.webp';

export function OwlMascot({ motion, labels }: { motion: boolean; labels: Locale['hero']['mascot'] }) {
    const viewerRef = useRef<ModelViewerElement | null>(null);
    const [ready, setReady] = useState(false);
    const [loaded, setLoaded] = useState(false);
    const [failed, setFailed] = useState(false);

    useEffect(() => {
        try {
            const context = document.createElement('canvas').getContext('webgl2');
            if (!context) {
                setFailed(true);
                return;
            }
            context.getExtension('WEBGL_lose_context')?.loseContext();
        } catch {
            setFailed(true);
            return;
        }

        let cancelled = false;
        import('@google/model-viewer').then(() => {
            if (!cancelled) setReady(true);
        }).catch(() => {
            if (!cancelled) setFailed(true);
        });
        return () => { cancelled = true; };
    }, []);

    useEffect(() => {
        const viewer = viewerRef.current;
        if (!ready || failed || !viewer) return;

        const bounds = viewer.getBoundingClientRect();
        let visible = bounds.bottom > 0 && bounds.top < window.innerHeight;
        let modelLoaded = viewer.loaded;
        const syncPlayback = () => {
            const shouldPlay = modelLoaded && motion && visible && !document.hidden;
            viewer.autoplay = shouldPlay;
            if (shouldPlay) viewer.play();
            else viewer.pause();
        };
        const onLoad = () => {
            modelLoaded = true;
            setLoaded(true);
            syncPlayback();
        };
        const onError = () => setFailed(true);
        const observer = new IntersectionObserver(([entry]) => {
            visible = entry.isIntersecting;
            syncPlayback();
        });

        viewer.addEventListener('load', onLoad);
        viewer.addEventListener('error', onError);
        document.addEventListener('visibilitychange', syncPlayback);
        observer.observe(viewer);
        if (viewer.loaded) onLoad();
        else syncPlayback();

        return () => {
            observer.disconnect();
            viewer.removeEventListener('load', onLoad);
            viewer.removeEventListener('error', onError);
            document.removeEventListener('visibilitychange', syncPlayback);
            viewer.pause();
        };
    }, [ready, failed, motion]);

    return (
        <div className="owl3d-wrap">
            <img
                className={'owl3d-poster' + (loaded && !failed ? ' is-hidden' : '')}
                src={POSTER_SRC}
                width={1040}
                height={920}
                alt={labels.alt}
                aria-hidden={loaded && !failed}
                draggable={false}
            />
            {ready && !failed && (
                <model-viewer
                    ref={viewerRef}
                    className={'owl3d-viewer' + (loaded ? ' is-loaded' : '')}
                    src="/assets/flameowl.glb"
                    alt={labels.alt}
                    aria-hidden={!loaded}
                    loading="eager"
                    animation-name="Flameowl_Ember_Idle"
                    camera-controls=""
                    camera-orbit="0deg 90deg 105%"
                    min-camera-orbit="auto 0deg auto"
                    max-camera-orbit="auto 180deg auto"
                    disable-pan=""
                    disable-zoom=""
                    touch-action="none"
                    interaction-prompt="none"
                    environment-image="neutral"
                    tone-mapping="neutral"
                    exposure="1"
                    shadow-intensity="0"
                />
            )}
        </div>
    );
}
