import { useState, useEffect, useRef, useCallback } from 'react';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faSidebarFlip, faSidebar, faPhone, faXmark, faDeleteLeft, faFlask, faMagnifyingGlass, faCircleInfo } from '@fortawesome/pro-duotone-svg-icons';
import { useSetAtom } from 'jotai';
import { sipCallStateAtom, sipCallerNumberAtom, sipCallUcidAtom, sipCallDurationAtom } from '@/state/sip-state';
import { useAuth } from '@/providers/auth-provider';
import { useData } from '@/providers/data-provider';
import { useWorklist } from '@/hooks/use-worklist';
import { useSip } from '@/providers/sip-provider';
import { WorklistPanel } from '@/components/call-desk/worklist-panel';
import type { WorklistSelection } from '@/components/call-desk/worklist-panel';
import { ContextPanel } from '@/components/call-desk/context-panel';
import type { ContextPanelSubject } from '@/components/call-desk/context-panel';
import { ActiveCallCard } from '@/components/call-desk/active-call-card';
import { Input } from '@/components/base/input/input';
import { faIcon } from '@/lib/icon-wrapper';

import { apiClient } from '@/lib/api-client';
import { notify } from '@/lib/toast';
import { cx } from '@/utils/cx';

const SearchLg = faIcon(faMagnifyingGlass);

export const CallDeskPage = () => {
    const { user } = useAuth();
    const { leadActivities, calls, followUps: dataFollowUps, patients, appointments } = useData();
    const { callState, callerNumber, callUcid, dialOutbound, isRegistered } = useSip();
    const { missedCalls, followUps, marketingLeads, loading } = useWorklist();
    const [selectedLead, setSelectedLead] = useState<ContextPanelSubject | null>(null);
    const [selectedItemId, setSelectedItemId] = useState<string | null>(null);
    const [contextOpen, setContextOpen] = useState(true);
    const [activeMissedCallId, setActiveMissedCallId] = useState<string | null>(null);
    const [callDismissed, setCallDismissed] = useState(false);
    const [diallerOpen, setDiallerOpen] = useState(false);
    const [dialNumber, setDialNumber] = useState('');
    const [dialling, setDialling] = useState(false);
    const [search, setSearch] = useState('');

    // DEV: simulate incoming call
    const setSimCallState = useSetAtom(sipCallStateAtom);
    const setSimCallerNumber = useSetAtom(sipCallerNumberAtom);
    const setSimCallUcid = useSetAtom(sipCallUcidAtom);
    const setSimDuration = useSetAtom(sipCallDurationAtom);
    const simTimerRef = useRef<ReturnType<typeof setInterval> | null>(null);

    const startSimCall = useCallback(() => {
        setSimCallerNumber('+919959966676');
        setSimCallUcid(`SIM-${Date.now()}`);
        setSimDuration(0);
        setSimCallState('active');
        simTimerRef.current = setInterval(() => setSimDuration((d) => d + 1), 1000);
    }, [setSimCallState, setSimCallerNumber, setSimCallUcid, setSimDuration]);

    const endSimCall = useCallback(() => {
        if (simTimerRef.current) { clearInterval(simTimerRef.current); simTimerRef.current = null; }
        setSimCallState('idle');
        setSimCallerNumber(null);
        setSimCallUcid(null);
        setSimDuration(0);
    }, [setSimCallState, setSimCallerNumber, setSimCallUcid, setSimDuration]);

    const handleDial = async () => {
        const num = dialNumber.replace(/[^0-9]/g, '');
        if (num.length < 10) { notify.error('Enter a valid phone number'); return; }
        setDialling(true);
        try {
            await dialOutbound(num);
            setDiallerOpen(false);
            setDialNumber('');
        } catch {
            notify.error('Dial failed');
        } finally {
            setDialling(false);
        }
    };

    // Reset callDismissed when a new call starts (ringing in or out)
    if (callDismissed && (callState === 'ringing-in' || callState === 'ringing-out')) {
        setCallDismissed(false);
    }

    const isInCall = !callDismissed && (callState === 'ringing-in' || callState === 'ringing-out' || callState === 'active' || callState === 'ended' || callState === 'failed');

    // Resolve caller identity via sidecar (lookup-or-create lead+patient pair)
    const [resolvedCaller, setResolvedCaller] = useState<{
        leadId: string; patientId: string; firstName: string; lastName: string; phone: string;
    } | null>(null);
    const resolveAttemptedRef = useRef<string | null>(null);

    useEffect(() => {
        if (!callerNumber || !isInCall) return;
        if (resolveAttemptedRef.current === callerNumber) return; // already resolving/resolved this number
        resolveAttemptedRef.current = callerNumber;

        apiClient.post<{
            leadId: string; patientId: string; firstName: string; lastName: string; phone: string; isNew: boolean;
        }>('/api/caller/resolve', { phone: callerNumber }, { silent: true })
            .then((result) => {
                setResolvedCaller(result);
                if (result.isNew) {
                    notify.info('New Caller', 'No existing records found for this number');
                }
            })
            .catch((err) => {
                console.warn('[RESOLVE] Caller resolution failed:', err);
                resolveAttemptedRef.current = null; // allow retry
            });
    }, [callerNumber, isInCall]);

    // Reset resolved caller when call ends
    useEffect(() => {
        if (!isInCall) {
            setResolvedCaller(null);
            resolveAttemptedRef.current = null;
        }
    }, [isInCall]);

    // Build activeLead from resolved caller or fallback to client-side match.
    // The resolver is the authoritative source for patientId (it just joined
    // lead↔patient by phone), so overlay it on top of any worklist row that
    // pre-dates the linkage. Without this, the Book Appt pills can't find
    // a returning caller's prior appointments because the frontend loses
    // sight of which patient they are.
    const workLead = resolvedCaller ? marketingLeads.find((l) => l.id === resolvedCaller.leadId) : null;
    const callerLead = resolvedCaller
        ? workLead
            ? { ...workLead, patientId: (workLead as any).patientId ?? resolvedCaller.patientId }
            : {
                id: resolvedCaller.leadId,
                contactName: { firstName: resolvedCaller.firstName, lastName: resolvedCaller.lastName },
                contactPhone: [{ number: resolvedCaller.phone, callingCode: '+91' }],
                patientId: resolvedCaller.patientId,
            }
        : callerNumber
            ? marketingLeads.find((l) => l.contactPhone?.[0]?.number?.endsWith(callerNumber) || callerNumber.endsWith(l.contactPhone?.[0]?.number ?? '---'))
            : null;

    // For inbound calls, use resolved/matched lead. For outbound, use selectedLead.
    const activeLead = isInCall
        ? (callerLead ?? (callState === 'ringing-out' ? selectedLead : null))
        : selectedLead;
    const activeLeadFull = activeLead as any;

    // Handle selection from any worklist row type. Leads use the lead
    // object directly; missed calls and follow-ups build a synthetic
    // lead-like object from their phone/patientId so the P360 context
    // panel can render for any row type.
    const handleSelectItem = useCallback((selection: WorklistSelection) => {
        setSelectedItemId(selection.rowId);

        if (selection.lead) {
            // Lead row — use the full lead object as before
            setSelectedLead(selection.lead);
            return;
        }

        // Non-lead row (missed call, follow-up, callback) — build a
        // ContextPanelSubject from the row's available data. The panel
        // uses contactPhone for call-history matching and patientId for
        // appointment/follow-up lookups. No type cast needed — the
        // ContextPanelSubject type accepts these optional fields.
        const phone = selection.phoneRaw ? selection.phoneRaw.replace(/\D/g, '').slice(-10) : '';
        const subject: ContextPanelSubject = {
            id: selection.leadId ?? selection.rowId,
            contactName: { firstName: selection.name.split(' ')[0] || '', lastName: selection.name.split(' ').slice(1).join(' ') || '' },
            contactPhone: phone ? [{ number: phone, callingCode: '+91' }] : [],
            patientId: selection.patientId,
        };
        setSelectedLead(subject);
    }, []);

    return (
        <div className="flex flex-1 flex-col overflow-hidden">
            {/* Header — matches PageHeader visual pattern */}
            <div className="flex shrink-0 items-center justify-between px-6 py-3">
                <div className="flex items-center gap-2">
                    <h1 className="text-lg font-bold text-primary">Call Desk</h1>
                    <span className="text-sm text-tertiary ml-1">{user.name}</span>
                    <span className="flex size-5 items-center justify-center text-fg-quaternary" title="Your active worklist — missed calls, leads, and follow-ups prioritised by SLA.">
                        <FontAwesomeIcon icon={faCircleInfo} className="size-4" />
                    </span>
                </div>

                <div className="flex items-center gap-2">
                    {!isInCall && (
                        <div className="w-52">
                            <Input
                                placeholder="Search worklist..."
                                icon={SearchLg}
                                size="sm"
                                value={search}
                                onChange={setSearch}
                                aria-label="Search worklist"
                            />
                        </div>
                    )}
                    {import.meta.env.DEV && (!isInCall ? (
                        <button
                            onClick={startSimCall}
                            className="flex items-center gap-1.5 px-3 py-1.5 rounded-lg text-xs font-medium bg-warning-secondary text-warning-primary hover:bg-warning-primary hover:text-white transition duration-100 ease-linear"
                        >
                            <FontAwesomeIcon icon={faFlask} className="size-3" />
                            Sim Call
                        </button>
                    ) : callUcid?.startsWith('SIM-') && (
                        <button
                            onClick={endSimCall}
                            className="flex items-center gap-1.5 px-3 py-1.5 rounded-lg text-xs font-medium bg-error-solid text-white hover:bg-error-solid_hover transition duration-100 ease-linear"
                        >
                            <FontAwesomeIcon icon={faFlask} className="size-3" />
                            End Sim
                        </button>
                    ))}
                    {!isInCall && (
                        <div className="relative">
                            <button
                                onClick={() => setDiallerOpen(!diallerOpen)}
                                className={cx(
                                    'flex items-center gap-1.5 px-3 py-1.5 rounded-lg text-xs font-medium transition duration-100 ease-linear',
                                    diallerOpen
                                        ? 'bg-brand-solid text-white'
                                        : 'bg-secondary text-secondary hover:bg-secondary_hover',
                                )}
                            >
                                <FontAwesomeIcon icon={faPhone} className="size-3" />
                                Dial
                            </button>
                            {diallerOpen && (
                                <div className="absolute top-full right-0 mt-2 w-72 rounded-xl bg-primary shadow-xl ring-1 ring-secondary p-4 z-50">
                                    <div className="flex items-center justify-between mb-3">
                                        <span className="text-sm font-semibold text-primary">Dial</span>
                                        <button onClick={() => setDiallerOpen(false)} className="text-fg-quaternary hover:text-fg-secondary">
                                            <FontAwesomeIcon icon={faXmark} className="size-4" />
                                        </button>
                                    </div>
                                    <div className="flex items-center gap-2 mb-3 px-3 py-2.5 rounded-lg bg-secondary min-h-[40px]">
                                        <input
                                            type="tel"
                                            value={dialNumber}
                                            onChange={e => setDialNumber(e.target.value)}
                                            onKeyDown={e => e.key === 'Enter' && handleDial()}
                                            placeholder="Enter number"
                                            autoFocus
                                            className="flex-1 bg-transparent text-lg font-semibold text-primary tracking-wider text-center placeholder:text-placeholder placeholder:font-normal placeholder:text-sm outline-none"
                                        />
                                        {dialNumber && (
                                            <button onClick={() => setDialNumber(dialNumber.slice(0, -1))} className="text-fg-quaternary hover:text-fg-secondary shrink-0">
                                                <FontAwesomeIcon icon={faDeleteLeft} className="size-4" />
                                            </button>
                                        )}
                                    </div>
                                    <div className="grid grid-cols-3 gap-1.5 mb-3">
                                        {['1', '2', '3', '4', '5', '6', '7', '8', '9', '*', '0', '#'].map(key => (
                                            <button
                                                key={key}
                                                onClick={() => setDialNumber(prev => prev + key)}
                                                className="flex items-center justify-center h-11 rounded-lg text-sm font-semibold text-primary bg-primary hover:bg-secondary border border-secondary transition duration-100 ease-linear active:scale-95"
                                            >
                                                {key}
                                            </button>
                                        ))}
                                    </div>
                                    <button
                                        onClick={handleDial}
                                        disabled={!isRegistered || dialling || dialNumber.replace(/[^0-9]/g, '').length < 10}
                                        className="w-full flex items-center justify-center gap-2 rounded-lg bg-success-solid py-2.5 text-sm font-medium text-white hover:opacity-90 disabled:bg-disabled disabled:cursor-not-allowed transition duration-100 ease-linear"
                                    >
                                        <FontAwesomeIcon icon={faPhone} className="size-3.5" />
                                        {dialling ? 'Dialling...' : !isRegistered ? 'Telephony unavailable' : 'Call'}
                                    </button>
                                </div>
                            )}
                        </div>
                    )}
                    <button
                        onClick={() => setContextOpen(!contextOpen)}
                        className="flex size-8 items-center justify-center rounded-lg text-fg-quaternary hover:text-fg-secondary hover:bg-primary_hover transition duration-100 ease-linear"
                        title={contextOpen ? 'Hide AI panel' : 'Show AI panel'}
                    >
                        <FontAwesomeIcon icon={contextOpen ? faSidebarFlip : faSidebar} className="size-4" />
                    </button>
                </div>
            </div>

            {/* Main content */}
            <div className="flex flex-1 overflow-hidden">
                {/* Main panel */}
                <div className="flex flex-1 flex-col min-h-0 overflow-hidden">
                    {/* Active call */}
                    {isInCall && (
                        <div className="flex flex-col flex-1 min-h-0 overflow-hidden p-5">
                            <ActiveCallCard lead={activeLeadFull} callerPhone={callerNumber ?? ''} missedCallId={activeMissedCallId} onCallComplete={() => { setActiveMissedCallId(null); setCallDismissed(true); }} />
                        </div>
                    )}

                    {/* Worklist — no wrapper, tabs + table fill the space */}
                    {!isInCall && (
                        <WorklistPanel
                            missedCalls={missedCalls}
                            followUps={followUps}
                            leads={marketingLeads}
                            loading={loading}
                            onSelectItem={handleSelectItem}
                            selectedItemId={selectedItemId}
                            onDialMissedCall={(id) => setActiveMissedCallId(id)}
                            search={search}
                        />
                    )}
                </div>

                {/* Context panel — collapsible with smooth transition */}
                <div className={cx(
                    "shrink-0 border-l border-secondary bg-primary flex flex-col overflow-hidden transition-all duration-200 ease-linear",
                    contextOpen ? "w-[400px]" : "w-0 border-l-0",
                )}>
                    {contextOpen && (
                        <ContextPanel
                            selectedLead={activeLeadFull}
                            activities={leadActivities}
                            calls={calls}
                            followUps={dataFollowUps}
                            appointments={appointments}
                            patients={patients}
                            callerPhone={callerNumber ?? undefined}
                            isInCall={isInCall}
                            callUcid={callUcid}
                        />
                    )}
                </div>
            </div>

        </div>
    );
};
