import { Info } from 'lucide-react';
import { createContext, useContext, useEffect, useState } from 'react';
import type { ReactNode } from 'react';
import type { GrowBetterDirection, GrowBetterHelp } from '@/types/grow-better';

type HelpRequest = {
    title: string;
    direction: GrowBetterDirection | null;
    help: GrowBetterHelp;
    x: number;
    y: number;
};

const HelpContext = createContext<((request: HelpRequest) => void) | null>(
    null,
);

const directionCopy: Record<
    GrowBetterDirection,
    { label: string; className: string }
> = {
    higher: {
        label: 'Higher is better',
        className: 'bg-emerald-500/10 text-emerald-700 dark:text-emerald-300',
    },
    lower: {
        label: 'Lower is better',
        className: 'bg-amber-500/10 text-amber-700 dark:text-amber-300',
    },
    balanced: {
        label: 'Best kept in a healthy range',
        className: 'bg-primary/10 text-primary',
    },
};

export function GrowBetterHelpProvider({ children }: { children: ReactNode }) {
    const [help, setHelp] = useState<HelpRequest | null>(null);

    useEffect(() => {
        const close = () => setHelp(null);
        window.addEventListener('resize', close);

        return () => window.removeEventListener('resize', close);
    }, []);

    useEffect(() => {
        if (!help) {
            return;
        }

        const close = (event: MouseEvent) => {
            const target = event.target;

            if (
                target instanceof Element &&
                target.closest('[aria-label^="Explain"]')
            ) {
                return;
            }

            setHelp(null);
        };

        document.addEventListener('click', close);

        return () => document.removeEventListener('click', close);
    }, [help]);

    return (
        <HelpContext.Provider value={setHelp}>
            {children}
            {help && (
                <div
                    className="fixed z-50 w-72 max-w-[calc(100vw-1.5rem)] rounded-xl border bg-popover p-4 text-popover-foreground shadow-xl"
                    style={{ left: help.x, top: help.y }}
                    onClick={(event) => event.stopPropagation()}
                >
                    <button
                        type="button"
                        className="absolute top-3 right-3 text-muted-foreground"
                        onClick={() => setHelp(null)}
                        aria-label="Close explanation"
                    >
                        ×
                    </button>
                    <h3 className="pr-6 text-sm font-semibold">{help.title}</h3>
                    {help.direction && (
                        <p
                            className={`mt-2 inline-flex rounded-full px-2.5 py-1 text-[11px] font-semibold ${directionCopy[help.direction].className}`}
                        >
                            {directionCopy[help.direction].label}
                        </p>
                    )}
                    <p className="mt-3 text-xs leading-relaxed text-muted-foreground">
                        {help.help.what}
                    </p>
                    <p className="mt-3 border-l-2 border-primary pl-3 text-xs leading-relaxed">
                        <span className="font-semibold">Why it matters: </span>
                        {help.help.why}
                    </p>
                </div>
            )}
        </HelpContext.Provider>
    );
}

export function InfoButton({
    title,
    help,
    direction = null,
}: {
    title: string;
    help: GrowBetterHelp;
    direction?: GrowBetterDirection | null;
}) {
    const open = useContext(HelpContext);

    return (
        <button
            type="button"
            className="inline-flex size-3.5 shrink-0 items-center justify-center rounded-full border text-[9px] text-muted-foreground hover:border-primary hover:text-primary"
            aria-label={`Explain ${title}`}
            onClick={(event) => {
                event.preventDefault();
                event.stopPropagation();
                const rect = event.currentTarget.getBoundingClientRect();
                const width = 288;
                let left = rect.left;
                let top = rect.bottom + 8;

                if (left + width > window.innerWidth - 12) {
                    left = window.innerWidth - width - 12;
                }

                if (top + 220 > window.innerHeight - 12) {
                    top = Math.max(12, rect.top - 220);
                }

                open?.({
                    title,
                    direction,
                    help,
                    x: Math.max(12, left),
                    y: top,
                });
            }}
        >
            <Info className="size-2.5" />
        </button>
    );
}
