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

const getSipConfig = (): SIPConfig => {
    try {
        const stored = localStorage.getItem('helix_agent_config');
        if (stored) {
            const config = JSON.parse(stored);
            return {
                displayName: 'Helix Agent',
                uri: config.sipUri,
                password: config.sipPassword,
                wsServer: config.sipWsServer,
                stunServers: 'stun:stun.l.google.com:19302',
            };
        }
    } catch {}
    return {
        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 setCallUcid = useSetAtom(sipCallUcidAtom);
    const setCallDuration = useSetAtom(sipCallDurationAtom);
    const setCallStartTime = useSetAtom(sipCallStartTimeAtom);

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

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

    // 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]);

    // Ringtone on incoming call
    useEffect(() => {
        if (callState === 'ringing-in') {
            import('@/lib/ringtone').then(({ startRingtone }) => startRingtone());
        } else {
            import('@/lib/ringtone').then(({ stopRingtone }) => stopRingtone());
        }
    }, [callState]);

    // No auto-reset — the ActiveCallCard handles post-call flow (disposition → appointment → done)
    // and resets to idle via the "Back to Worklist" button

    // 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 [callUcid] = useAtom(sipCallUcidAtom);
    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,
        callUcid,
        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(getSipConfig()),
        disconnect: disconnectSip,
        makeCall,
        answer,
        reject,
        hangup,
        toggleMute,
        toggleHold,
    };
};
