import { useEffect, useCallback, type PropsWithChildren } from 'react';
import { useAtom, useSetAtom } from 'jotai';
import {
    sipConnectionStatusAtom,
    sipCallStateAtom,
    sipCallerNumberAtom,
    sipIsMutedAtom,
    sipIsOnHoldAtom,
    sipCallDurationAtom,
    sipCallStartTimeAtom,
} from '@/state/sip-state';
import { registerSipStateUpdater, connectSip, disconnectSip, getSipClient } from '@/state/sip-manager';
import type { SIPConfig } from '@/types/sip';

const DEFAULT_CONFIG: SIPConfig = {
    displayName: import.meta.env.VITE_SIP_DISPLAY_NAME ?? 'Helix Agent',
    uri: import.meta.env.VITE_SIP_URI ?? '',
    password: import.meta.env.VITE_SIP_PASSWORD ?? '',
    wsServer: import.meta.env.VITE_SIP_WS_SERVER ?? '',
    stunServers: 'stun:stun.l.google.com:19302',
};

export const SipProvider = ({ children }: PropsWithChildren) => {
    const [, setConnectionStatus] = useAtom(sipConnectionStatusAtom);
    const [callState, setCallState] = useAtom(sipCallStateAtom);
    const setCallerNumber = useSetAtom(sipCallerNumberAtom);
    const setCallDuration = useSetAtom(sipCallDurationAtom);
    const setCallStartTime = useSetAtom(sipCallStartTimeAtom);

    // Register Jotai setters so the singleton SIP manager can update atoms
    useEffect(() => {
        registerSipStateUpdater({
            setConnectionStatus,
            setCallState,
            setCallerNumber,
        });
    }, [setConnectionStatus, setCallState, setCallerNumber]);

    // Auto-connect SIP on mount
    useEffect(() => {
        connectSip(DEFAULT_CONFIG);
    }, []);

    // Call duration timer
    useEffect(() => {
        if (callState === 'active') {
            const start = new Date();
            setCallStartTime(start);
            const interval = window.setInterval(() => {
                setCallDuration(Math.floor((Date.now() - start.getTime()) / 1000));
            }, 1000);
            return () => clearInterval(interval);
        }
        setCallDuration(0);
        setCallStartTime(null);
    }, [callState, setCallDuration, setCallStartTime]);

    // Auto-reset to idle after ended/failed
    useEffect(() => {
        if (callState === 'ended' || callState === 'failed') {
            const timer = setTimeout(() => {
                setCallState('idle');
                setCallerNumber(null);
            }, 2000);
            return () => clearTimeout(timer);
        }
    }, [callState, setCallState, setCallerNumber]);

    // Cleanup on page unload
    useEffect(() => {
        const handleUnload = () => disconnectSip();
        window.addEventListener('beforeunload', handleUnload);
        return () => window.removeEventListener('beforeunload', handleUnload);
    }, []);

    return <>{children}</>;
};

// Hook for components to access SIP actions + state
export const useSip = () => {
    const [connectionStatus] = useAtom(sipConnectionStatusAtom);
    const [callState] = useAtom(sipCallStateAtom);
    const [callerNumber, setCallerNumber] = useAtom(sipCallerNumberAtom);
    const [isMuted, setIsMuted] = useAtom(sipIsMutedAtom);
    const [isOnHold, setIsOnHold] = useAtom(sipIsOnHoldAtom);
    const [callDuration] = useAtom(sipCallDurationAtom);

    const makeCall = useCallback((phoneNumber: string) => {
        getSipClient()?.call(phoneNumber);
        setCallerNumber(phoneNumber);
    }, [setCallerNumber]);

    const answer = useCallback(() => getSipClient()?.answer(), []);
    const reject = useCallback(() => getSipClient()?.reject(), []);
    const hangup = useCallback(() => getSipClient()?.hangup(), []);

    const toggleMute = useCallback(() => {
        if (isMuted) {
            getSipClient()?.unmute();
        } else {
            getSipClient()?.mute();
        }
        setIsMuted(!isMuted);
    }, [isMuted, setIsMuted]);

    const toggleHold = useCallback(() => {
        if (isOnHold) {
            getSipClient()?.unhold();
        } else {
            getSipClient()?.hold();
        }
        setIsOnHold(!isOnHold);
    }, [isOnHold, setIsOnHold]);

    return {
        connectionStatus,
        callState,
        callerNumber,
        isMuted,
        isOnHold,
        callDuration,
        isRegistered: connectionStatus === 'registered',
        isInCall: ['ringing-in', 'ringing-out', 'active'].includes(callState),
        ozonetelStatus: 'logged-in' as const,
        ozonetelError: null as string | null,
        connect: () => connectSip(DEFAULT_CONFIG),
        disconnect: disconnectSip,
        makeCall,
        answer,
        reject,
        hangup,
        toggleMute,
        toggleHold,
    };
};
