import Logo from '../../assets/chowman-bg-logo.avif';
import { useEffect, useLayoutEffect, useRef, useState } from 'react';
import { useQuizFlow, useQuiz, useQuizTimer } from '@/features/quiz/hooks';
import { QuizRouteGuard } from '@/features/quiz/components';
import { Spinner } from '@/components/ui/spinner';
import { ArrowRight } from 'lucide-react';
import type { QuizOptionKey } from '@/features/quiz/context';
import Thinking from '../../assets/thinking.avif';

type OptionStatus = 'correct' | 'wrong' | null;

/** Target pulses per second for a given time left */
const getTargetFrequency = (timeLeft: number) => {
    if (timeLeft > 10) return 1;
    if (timeLeft > 3) return 2;
    return 3;
};

const ThinkingPeek = () => {
    const ref = useRef<HTMLImageElement>(null);

    useLayoutEffect(() => {
        const el = ref.current;
        if (!el) return;
        if (window.matchMedia('(prefers-reduced-motion: reduce)').matches)
            return;

        const animation = el.animate(
            [{ transform: 'translateY(100%)' }, { transform: 'translateY(0)' }],
            {
                duration: 1900,
                delay: 200,
                easing: 'cubic-bezier(0.22, 1, 0.36, 1)',
                fill: 'backwards',
            },
        );

        return () => animation.cancel();
    }, []);

    return (
        <img
            ref={ref}
            src={Thinking}
            alt=""
            className="pointer-events-none absolute bottom-0 left-0 h-full max-h-44 w-auto max-w-none select-none"
        />
    );
};

const QuizApp = () => {
    const {
        currentQuestion,
        answerFeedback,
        feedbackVisible,
        isSubmitting,
        isLoadingQuestion,
        campaign,
        timerDeadline,
    } = useQuiz();
    const { fetchCurrentQuestion, submitAnswer, handleTimeout } = useQuizFlow();
    const timeLeft = useQuizTimer();

    const [selectedOption, setSelectedOption] = useState<QuizOptionKey | null>(
        null,
    );
    const [hasSubmitted, setHasSubmitted] = useState(false);

    const pulseRef = useRef<HTMLSpanElement>(null);
    const pulseTarget = useRef({ freq: 1, amp: 1 });
    const timeoutRequestInFlightRef = useRef(false);

    // Fetch question on mount
    useEffect(() => {
        if (!currentQuestion && !isLoadingQuestion) {
            fetchCurrentQuestion();
        }
    }, [currentQuestion, isLoadingQuestion, fetchCurrentQuestion]);

    // Reset state when question changes
    useEffect(() => {
        if (currentQuestion) {
            setSelectedOption(null);
            setHasSubmitted(false);
            timeoutRequestInFlightRef.current = false;
        }
    }, [currentQuestion?.question_id]);

    // Handle timeout from timer
    useEffect(() => {
        if (
            currentQuestion &&
            timerDeadline &&
            timeLeft === 0 &&
            !hasSubmitted &&
            !feedbackVisible &&
            !isLoadingQuestion &&
            !timeoutRequestInFlightRef.current
        ) {
            timeoutRequestInFlightRef.current = true;
            void handleTimeout().catch(() => {
                timeoutRequestInFlightRef.current = false;
            });
        }
    }, [
        currentQuestion?.question_id,
        timerDeadline,
        timeLeft,
        hasSubmitted,
        feedbackVisible,
        isLoadingQuestion,
    ]);

    // Publish the targets whenever the countdown ticks
    useEffect(() => {
        pulseTarget.current = {
            freq: getTargetFrequency(timeLeft),
            amp: timeLeft > 0 ? 1 : 0,
        };
    }, [timeLeft]);

    // Continuous pulse: speed and strength ease toward the targets
    useEffect(() => {
        let frame = 0;
        let last = performance.now();
        let phase = 0;
        let freq = 1;
        let amp = 1;

        const tick = (now: number) => {
            const dt = Math.min((now - last) / 1000, 0.1);
            last = now;

            const target = pulseTarget.current;
            freq += (target.freq - freq) * (1 - Math.exp(-dt / 0.6));
            amp += (target.amp - amp) * (1 - Math.exp(-dt / 0.4));
            phase += Math.PI * 2 * freq * dt;

            const w = 0.5 + ((1 - Math.cos(phase)) / 2 - 0.5) * amp;

            const el = pulseRef.current;
            if (el) {
                el.style.transform = `scale(${0.88 + 0.12 * w})`;
                el.style.opacity = String(0.35 + 0.65 * w);
            }
            frame = requestAnimationFrame(tick);
        };

        frame = requestAnimationFrame(tick);
        return () => cancelAnimationFrame(frame);
    }, []);

    const isCritical = timeLeft < 10;
    const timerSeconds = campaign?.timer_seconds ?? 45;

    const getOptionStatus = (key: QuizOptionKey): OptionStatus => {
        if (!feedbackVisible || !answerFeedback) return null;

        if (key === answerFeedback.correct_option) return 'correct';
        if (key === selectedOption && !answerFeedback.is_correct)
            return 'wrong';

        return null;
    };

    const handleSubmit = async () => {
        if (!selectedOption || !currentQuestion || hasSubmitted) return;

        setHasSubmitted(true);
        try {
            await submitAnswer(currentQuestion.question_id, selectedOption);
        } catch {
            // Keep the answer selectable if a network retry is required.
            setHasSubmitted(false);
        }
    };

    if (isLoadingQuestion || !currentQuestion) {
        return (
            <main className="min-h-[100dvh] px-5 py-8 sm:px-8 lg:px-12">
                <div className="mx-auto flex min-h-[calc(100dvh-64px)] w-full max-w-full flex-col items-center justify-center">
                    <Spinner
                        size="lg"
                        className="text-[#D4A24E]"
                    />
                </div>
            </main>
        );
    }

    const options = currentQuestion.options;
    const isLocked = feedbackVisible || hasSubmitted || timeLeft === 0;

    // Keep the final question mounted while its two-second feedback period
    // runs. The flow then takes the player to /loading.
    return (
        <QuizRouteGuard allowedStates={['new', 'in_progress', 'completed']}>
            <main className="flex min-h-[100dvh] flex-col overflow-x-hidden px-5 py-[clamp(12px,2.5dvh,32px)] sm:px-8 lg:px-12">
                <div className="mx-auto flex w-full max-w-full flex-1 flex-col">
                    {/* Logo */}
                    <div className="flex shrink-0 justify-center">
                        <img
                            src={Logo}
                            className="h-[clamp(28px,5dvh,48px)] w-auto"
                            alt="Chowman Logo"
                        />
                    </div>

                    {/* Question Header */}
                    <div className="mt-[clamp(8px,2dvh,40px)] shrink-0">
                        <div className="flex items-end justify-between">
                            <div>
                                <p className="font-montserrat text-xs font-bold tracking-[0.3em] text-[#D4A24E] uppercase sm:text-sm">
                                    Question
                                </p>
                                <div className="mt-1 flex items-baseline">
                                    <span className="font-amethyst text-[clamp(1.75rem,5dvh,3rem)] leading-none tracking-widest text-[#FFF8EA]">
                                        {String(
                                            currentQuestion.question_index,
                                        ).padStart(2, '0')}
                                    </span>
                                    <span className="text-xl sm:text-2xl text-[#FFF8EA]">
                                        /
                                    </span>
                                    <span className="font-amethyst text-2xl tracking-widest text-[#FFF8EA] sm:text-2xl">
                                        {currentQuestion.progress.total}
                                    </span>
                                </div>
                            </div>

                            {/* Timer */}
                            <div className="relative flex h-[clamp(56px,9dvh,82px)] w-[clamp(56px,9dvh,82px)] shrink-0 items-center justify-center">
                                <span
                                    ref={pulseRef}
                                    className={`pointer-events-none absolute inset-[-8px] rounded-full border-2 transition-colors duration-700 ${isCritical ? 'border-[#D9803F]' : 'border-[#D4A24E]'}`}
                                />
                                <div
                                    className={`relative z-10 flex h-full w-full items-center justify-center rounded-full transition-colors duration-700 ${
                                        isCritical ? 'text-[#EE9A5C]' : 'text-[#D4A24E]'
                                    }`}
                                >
                                    {/* Progress ring: faint track + shrinking arc */}
                                    <svg
                                        className="pointer-events-none absolute inset-0 h-full w-full -rotate-90"
                                        viewBox="0 0 100 100"
                                        aria-hidden="true"
                                    >
                                        <circle
                                            cx="50"
                                            cy="50"
                                            r="48"
                                            fill="none"
                                            strokeWidth="3"
                                            className="stroke-[#70451F]/70"
                                        />
                                        <circle
                                            cx="50"
                                            cy="50"
                                            r="48"
                                            fill="none"
                                            strokeWidth="3"
                                            strokeLinecap="round"
                                            pathLength={1}
                                            strokeDasharray={1}
                                            strokeDashoffset={1 - Math.max(0, Math.min(1, (timeLeft - 1) / timerSeconds))}
                                            className={`transition-[stroke-dashoffset,stroke] duration-1000 ease-linear ${
                                                isCritical ? 'stroke-[#D9803F]' : 'stroke-[#D4A24E]'
                                            }`}
                                        />
                                    </svg>

                                    <div className="flex flex-col items-center">
                                        <span className="font-amethyst text-xl leading-none sm:text-2xl">
                                            {timeLeft}
                                        </span>
                                        <span className="mt-1 font-montserrat text-[9px] font-bold tracking-wider uppercase sm:text-[10px]">
                                            Sec
                                        </span>
                                    </div>
                                </div>
                            </div>
                        </div>

                        <div className="mt-[clamp(10px,2.5dvh,28px)] h-px w-full bg-[#70451F]/70" />
                        <div className="mt-2 h-1 overflow-hidden rounded-full bg-[#70451F]/70">
                            <div
                                className={`h-full transition-[width,background-color] duration-500 ${isCritical ? 'bg-[#D9803F]' : 'bg-[#D4A24E]'}`}
                                style={{
                                    width: `${Math.max(0, Math.min(100, (currentQuestion.question_index / currentQuestion.progress.total) * 100))}%`,
                                }}
                                aria-hidden="true"
                            />
                        </div>
                    </div>

                    {/* Question */}
                    <div className="mt-[clamp(8px,2dvh,40px)] shrink-0">
                        <p className="text-center font-montserrat text-xs font-bold tracking-[0.25em] text-[#D4A24E] uppercase sm:text-sm">
                            Durga Puja Trivia
                        </p>
                        <h1 className="mt-[clamp(6px,1.5dvh,20px)] text-center font-amethyst text-[clamp(1.25rem,3.6dvh,3rem)] leading-[1.1] !font-light text-[#FFF8EA]">
                            {currentQuestion.text}
                        </h1>
                    </div>

                    {/* Options */}
                    <div className="mt-[clamp(8px,2dvh,40px)] flex shrink-0 flex-col gap-[clamp(6px,1.2dvh,16px)]">
                        {options.map((option) => {
                            const status = getOptionStatus(option.key);
                            const isSelected = selectedOption === option.key;

                            return (
                                <button
                                    key={option.key}
                                    type="button"
                                    onClick={() =>
                                        !isLocked &&
                                        setSelectedOption(option.key)
                                    }
                                    disabled={isLocked}
                                    className={`flex min-h-[clamp(46px,7dvh,72px)] w-full items-center gap-3 rounded-xl border-2 px-4 py-1 text-left transition-all sm:gap-4 sm:px-6 ${
                                        status === 'correct'
                                            ? 'border-[#6DB887] bg-[#6DB887]/10'
                                            : status === 'wrong'
                                              ? 'border-[#B6533B] bg-[#B6533B]/10'
                                              : isSelected
                                                ? 'border-[#D4A24E] bg-[#D4A24E]/15 shadow-[0_0_18px_rgba(212,162,78,0.18)]'
                                                : 'border-[#70451F] bg-transparent hover:border-[#A77C35]'
                                    } ${isLocked ? 'cursor-not-allowed' : 'cursor-pointer'}`}
                                >
                                    <span
                                        className={`flex h-[clamp(26px,4.5dvh,36px)] w-[clamp(26px,4.5dvh,36px)] shrink-0 items-center justify-center rounded-full border-2 font-montserrat text-sm font-semibold transition-all ${
                                            status === 'correct'
                                                ? 'border-[#6DB887] bg-[#6DB887] text-[#230505]'
                                                : status === 'wrong'
                                                  ? 'border-[#B6533B] bg-[#B6533B] text-[#230505]'
                                                  : isSelected
                                                    ? 'border-[#E7C27A] bg-[#D4A24E] text-[#230505] shadow-[0_0_10px_rgba(212,162,78,0.35)]'
                                                    : 'border-[#A77C35] text-[#D4A24E]'
                                        }`}
                                    >
                                        {status === 'correct'
                                            ? '✓'
                                            : status === 'wrong'
                                              ? '×'
                                              : option.key}
                                    </span>

                                    <span
                                        className={`flex-1 font-montserrat text-[clamp(0.8125rem,2.2dvh,1.25rem)] transition-colors ${
                                            isSelected && !status
                                                ? 'font-semibold text-[#FFF8EA]'
                                                : 'text-[#FFF8EA]'
                                        }`}
                                    >
                                        {option.text}
                                    </span>
                                </button>
                            );
                        })}
                    </div>

                    {/* Flexible image area: fills leftover space, never smaller than 80px */}
                    <div className="relative mt-2 min-h-[80px] flex-1 overflow-hidden">
                        <ThinkingPeek key={currentQuestion.question_id} />
                    </div>

                    {/* Submit */}
                    <button
                        onClick={handleSubmit}
                        disabled={!selectedOption || isLocked || isSubmitting}
                        className={`relative z-10 flex h-[clamp(44px,7dvh,84px)] w-full shrink-0 items-center justify-center gap-2 rounded-xl border bg-gradient-to-b font-montserrat text-sm font-bold text-[#230505] transition-opacity sm:text-[22px] lg:text-[27px] ${
                            !selectedOption || isLocked || isSubmitting
                                ? 'cursor-not-allowed border-transparent from-[#653623] to-[#653623]'
                                : 'border-[#F0D28E] from-[#E7C27A] to-[#CEA052]'
                        }`}
                    >
                        {isSubmitting ? 'Submitting...' : 'Submit'}
                        {!isSubmitting && <ArrowRight className="h-5 w-5" />}
                    </button>
                </div>
            </main>
        </QuizRouteGuard>
    );
};

export default QuizApp;
