import { useMemo, useRef, useState } from 'react';
import type { FC } from 'react';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import {
    faPhoneArrowDown,
    faPhoneArrowUp,
    faPhoneXmark,
    faPlay,
    faPause,
} from '@fortawesome/pro-duotone-svg-icons';
import { SearchLg } from '@untitledui/icons';
import { Table, TableCard } from '@/components/application/table/table';
import { Badge } from '@/components/base/badges/badges';
import { Button } from '@/components/base/buttons/button';
import { Input } from '@/components/base/input/input';
import { Select } from '@/components/base/select/select';
import { TopBar } from '@/components/layout/top-bar';
import { ClickToCallButton } from '@/components/call-desk/click-to-call-button';
import { formatShortDate, formatPhone } from '@/lib/format';
import { useData } from '@/providers/data-provider';
import type { Call, CallDirection, CallDisposition } from '@/types/entities';

type FilterKey = 'all' | 'inbound' | 'outbound' | 'missed';

const filterItems = [
    { id: 'all' as const, label: 'All Calls' },
    { id: 'inbound' as const, label: 'Inbound' },
    { id: 'outbound' as const, label: 'Outbound' },
    { id: 'missed' as const, label: 'Missed' },
];

const dispositionConfig: Record<CallDisposition, { label: string; color: 'success' | 'brand' | 'blue-light' | 'warning' | 'gray' | 'error' }> = {
    APPOINTMENT_BOOKED: { label: 'Appt Booked', color: 'success' },
    FOLLOW_UP_SCHEDULED: { label: 'Follow-up', color: 'brand' },
    INFO_PROVIDED: { label: 'Info Provided', color: 'blue-light' },
    NO_ANSWER: { label: 'No Answer', color: 'warning' },
    WRONG_NUMBER: { label: 'Wrong Number', color: 'gray' },
    CALLBACK_REQUESTED: { label: 'Callback', color: 'brand' },
};

const formatDuration = (seconds: number | null): string => {
    if (seconds === null || seconds === 0) return '\u2014';
    if (seconds < 60) return `${seconds}s`;
    const mins = Math.floor(seconds / 60);
    const secs = seconds % 60;
    return secs > 0 ? `${mins}m ${secs}s` : `${mins}m`;
};

const formatPhoneDisplay = (call: Call): string => {
    if (call.callerNumber && call.callerNumber.length > 0) {
        return formatPhone(call.callerNumber[0]);
    }
    return '\u2014';
};

const DirectionIcon: FC<{ direction: CallDirection | null; status: Call['callStatus'] }> = ({ direction, status }) => {
    if (status === 'MISSED') {
        return <FontAwesomeIcon icon={faPhoneXmark} className="size-4 text-fg-error-secondary" />;
    }
    if (direction === 'OUTBOUND') {
        return <FontAwesomeIcon icon={faPhoneArrowUp} className="size-4 text-fg-brand-secondary" />;
    }
    return <FontAwesomeIcon icon={faPhoneArrowDown} className="size-4 text-fg-success-secondary" />;
};

const RecordingPlayer: FC<{ url: string }> = ({ url }) => {
    const audioRef = useRef<HTMLAudioElement>(null);
    const [isPlaying, setIsPlaying] = useState(false);

    const togglePlay = () => {
        const audio = audioRef.current;
        if (!audio) return;
        if (isPlaying) {
            audio.pause();
            setIsPlaying(false);
        } else {
            audio.play().catch(() => setIsPlaying(false));
            setIsPlaying(true);
        }
    };

    const handleEnded = () => setIsPlaying(false);

    return (
        <>
            <audio ref={audioRef} src={url} preload="none" onEnded={handleEnded} />
            <Button
                size="sm"
                color="tertiary"
                iconLeading={
                    <FontAwesomeIcon
                        icon={isPlaying ? faPause : faPlay}
                        data-icon
                        className="size-3.5"
                    />
                }
                onClick={togglePlay}
                aria-label={isPlaying ? 'Pause recording' : 'Play recording'}
            />
        </>
    );
};

export const CallHistoryPage = () => {
    const { calls, leads } = useData();
    const [search, setSearch] = useState('');
    const [filter, setFilter] = useState<FilterKey>('all');

    // Build a map of lead names by ID for enrichment
    const leadNameMap = useMemo(() => {
        const map = new Map<string, string>();
        for (const lead of leads) {
            if (lead.id && lead.contactName) {
                const name = `${lead.contactName.firstName ?? ''} ${lead.contactName.lastName ?? ''}`.trim();
                if (name) map.set(lead.id, name);
            }
        }
        return map;
    }, [leads]);

    // Sort by time (newest first) and apply filters
    const filteredCalls = useMemo(() => {
        let result = [...calls].sort((a, b) => {
            const dateA = a.startedAt ? new Date(a.startedAt).getTime() : 0;
            const dateB = b.startedAt ? new Date(b.startedAt).getTime() : 0;
            return dateB - dateA;
        });

        // Direction / status filter
        if (filter === 'inbound') result = result.filter((c) => c.callDirection === 'INBOUND');
        else if (filter === 'outbound') result = result.filter((c) => c.callDirection === 'OUTBOUND');
        else if (filter === 'missed') result = result.filter((c) => c.callStatus === 'MISSED');

        // Search filter
        if (search.trim()) {
            const q = search.toLowerCase();
            result = result.filter((c) => {
                const name = c.leadName ?? leadNameMap.get(c.leadId ?? '') ?? '';
                const phone = c.callerNumber?.[0]?.number ?? '';
                const agent = c.agentName ?? '';
                return (
                    name.toLowerCase().includes(q) ||
                    phone.includes(q) ||
                    agent.toLowerCase().includes(q)
                );
            });
        }

        return result;
    }, [calls, filter, search, leadNameMap]);

    const inboundCount = calls.filter((c) => c.callDirection === 'INBOUND').length;
    const outboundCount = calls.filter((c) => c.callDirection === 'OUTBOUND').length;
    const missedCount = calls.filter((c) => c.callStatus === 'MISSED').length;

    return (
        <div className="flex flex-1 flex-col overflow-hidden">
            <TopBar title="Call History" subtitle={`${calls.length} total calls`} />

            <div className="flex-1 overflow-y-auto p-7">
                <TableCard.Root size="md">
                    <TableCard.Header
                        title="Call History"
                        badge={String(filteredCalls.length)}
                        description={`${inboundCount} inbound \u00B7 ${outboundCount} outbound \u00B7 ${missedCount} missed`}
                        contentTrailing={
                            <div className="flex items-center gap-2">
                                <div className="w-44">
                                    <Select
                                        size="sm"
                                        placeholder="All Calls"
                                        selectedKey={filter}
                                        onSelectionChange={(key) => setFilter(key as FilterKey)}
                                        items={filterItems}
                                        aria-label="Filter calls"
                                    >
                                        {(item) => (
                                            <Select.Item id={item.id} label={item.label}>
                                                {item.label}
                                            </Select.Item>
                                        )}
                                    </Select>
                                </div>
                                <div className="w-56">
                                    <Input
                                        placeholder="Search calls..."
                                        icon={SearchLg}
                                        size="sm"
                                        value={search}
                                        onChange={(value) => setSearch(value)}
                                        aria-label="Search calls"
                                    />
                                </div>
                            </div>
                        }
                    />

                    {filteredCalls.length === 0 ? (
                        <div className="flex flex-col items-center justify-center py-16">
                            <h3 className="text-sm font-semibold text-primary">No calls found</h3>
                            <p className="text-sm text-tertiary mt-1">
                                {search ? 'Try a different search term' : 'No call history available yet.'}
                            </p>
                        </div>
                    ) : (
                        <Table>
                            <Table.Header>
                                <Table.Head label="TYPE" className="w-14" isRowHeader />
                                <Table.Head label="PATIENT" />
                                <Table.Head label="PHONE" />
                                <Table.Head label="DURATION" className="w-24" />
                                <Table.Head label="OUTCOME" />
                                <Table.Head label="AGENT" />
                                <Table.Head label="RECORDING" className="w-24" />
                                <Table.Head label="TIME" />
                                <Table.Head label="ACTIONS" className="w-24" />
                            </Table.Header>
                            <Table.Body items={filteredCalls}>
                                {(call) => {
                                    const patientName = call.leadName ?? leadNameMap.get(call.leadId ?? '') ?? 'Unknown';
                                    const phoneDisplay = formatPhoneDisplay(call);
                                    const phoneRaw = call.callerNumber?.[0]?.number ?? '';
                                    const dispositionCfg = call.disposition !== null ? dispositionConfig[call.disposition] : null;

                                    return (
                                        <Table.Row id={call.id}>
                                            <Table.Cell>
                                                <DirectionIcon direction={call.callDirection} status={call.callStatus} />
                                            </Table.Cell>
                                            <Table.Cell>
                                                <span className="text-sm font-medium text-primary truncate max-w-[160px] block">
                                                    {patientName}
                                                </span>
                                            </Table.Cell>
                                            <Table.Cell>
                                                <span className="text-sm text-tertiary whitespace-nowrap">
                                                    {phoneDisplay}
                                                </span>
                                            </Table.Cell>
                                            <Table.Cell>
                                                <span className="text-sm text-secondary whitespace-nowrap">
                                                    {formatDuration(call.durationSeconds)}
                                                </span>
                                            </Table.Cell>
                                            <Table.Cell>
                                                {dispositionCfg ? (
                                                    <Badge size="sm" color={dispositionCfg.color} type="pill-color">
                                                        {dispositionCfg.label}
                                                    </Badge>
                                                ) : (
                                                    <span className="text-sm text-quaternary">{'\u2014'}</span>
                                                )}
                                            </Table.Cell>
                                            <Table.Cell>
                                                <span className="text-sm text-secondary">
                                                    {call.agentName ?? '\u2014'}
                                                </span>
                                            </Table.Cell>
                                            <Table.Cell>
                                                {call.recordingUrl ? (
                                                    <RecordingPlayer url={call.recordingUrl} />
                                                ) : (
                                                    <span className="text-xs text-quaternary">{'\u2014'}</span>
                                                )}
                                            </Table.Cell>
                                            <Table.Cell>
                                                <span className="text-sm text-tertiary whitespace-nowrap">
                                                    {call.startedAt ? formatShortDate(call.startedAt) : '\u2014'}
                                                </span>
                                            </Table.Cell>
                                            <Table.Cell>
                                                {phoneRaw ? (
                                                    <ClickToCallButton
                                                        phoneNumber={phoneRaw}
                                                        leadId={call.leadId ?? undefined}
                                                        label="Call"
                                                        size="sm"
                                                    />
                                                ) : (
                                                    <span className="text-xs text-quaternary">{'\u2014'}</span>
                                                )}
                                            </Table.Cell>
                                        </Table.Row>
                                    );
                                }}
                            </Table.Body>
                        </Table>
                    )}
                </TableCard.Root>
            </div>
        </div>
    );
};
