import { createContext } from "preact";
import { useContext, useEffect } from "preact/hooks";
import { useStoredReducer } from "@common/hooks/useStored";
import { useBool } from "@common/hooks/useBool";
import {
    fetchUser, fetchWorkers, fetchPerformance, fetchModels,
    type WorkerData, type UserData, type PerformanceData, type ModelData,
} from "../utils/api";

// ── State ──────────────────────────────────────────────────────────────────

interface HordeState {
    apiKey: string;
    user: UserData | null;
    workers: WorkerData[];
    performance: PerformanceData | null;
    models: ModelData[];
}

const DEFAULT_STATE: HordeState = {
    apiKey: '',
    user: null,
    workers: [],
    performance: null,
    models: [],
};

// ── Actions ────────────────────────────────────────────────────────────────

type Action =
    | { type: 'SET_API_KEY'; apiKey: string }
    | { type: 'SET_USER'; user: UserData | null }
    | { type: 'SET_WORKERS'; workers: WorkerData[] }
    | { type: 'SET_PERFORMANCE'; performance: PerformanceData }
    | { type: 'SET_MODELS'; models: ModelData[] };

const reducer = (state: HordeState, action: Action): HordeState => {
    switch (action.type) {
        case 'SET_API_KEY': return { ...state, apiKey: action.apiKey, user: null };
        case 'SET_USER': return { ...state, user: action.user };
        case 'SET_WORKERS': return { ...state, workers: action.workers };
        case 'SET_PERFORMANCE': return { ...state, performance: action.performance };
        case 'SET_MODELS': return { ...state, models: action.models };
    }
};

// ── Context ────────────────────────────────────────────────────────────────

interface HordeContextValue {
    state: HordeState;
    dispatch: (action: Action) => void;
    leaderboard: ReturnType<typeof useBool>;
    options: ReturnType<typeof useBool>;
    manageWorkers: ReturnType<typeof useBool>;
}

const HordeContext = createContext<HordeContextValue>(null!);

export const useHordeState = () => useContext(HordeContext);

// ── Provider ───────────────────────────────────────────────────────────────

const POLL_INTERVAL_MS = 30_000;

export const HordeStateProvider = ({ children }: { children: preact.ComponentChildren }) => {
    const [state, dispatch] = useStoredReducer('state', reducer, DEFAULT_STATE);

    const leaderboard = useBool(false);
    const options = useBool(false);
    const manageWorkers = useBool(false);

    useEffect(() => {
        let cancelled = false;

        const poll = async () => {
            if (cancelled) return;

            // Always fetch workers, performance, models
            try {
                const [workers, performance, models] = await Promise.all([
                    fetchWorkers(),
                    fetchPerformance(),
                    fetchModels(),
                ]);
                if (!cancelled) {
                    dispatch({ type: 'SET_WORKERS', workers });
                    dispatch({ type: 'SET_PERFORMANCE', performance });
                    dispatch({ type: 'SET_MODELS', models });
                }
            } catch (e) {
                console.error('[horde] poll error:', e);
            }

            // Fetch user if apiKey is set
            if (state.apiKey && !cancelled) {
                try {
                    const user = await fetchUser(state.apiKey);
                    if (!cancelled) dispatch({ type: 'SET_USER', user });
                } catch {
                    if (!cancelled) dispatch({ type: 'SET_USER', user: null });
                }
            } else if (!state.apiKey && !cancelled) {
                dispatch({ type: 'SET_USER', user: null });
            }
        };

        poll();
        const id = setInterval(poll, POLL_INTERVAL_MS);
        return () => { cancelled = true; clearInterval(id); };
    }, [state.apiKey]);

    return (
        <HordeContext.Provider value={{ state, dispatch, leaderboard, options, manageWorkers }}>
            {children}
        </HordeContext.Provider>
    );
};
