import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { faPhoneArrowDown, faPhoneArrowUp, faMagnifyingGlass } from '@fortawesome/pro-duotone-svg-icons';
import type { SortDescriptor } from 'react-aria-components';
import { faIcon } from '@/lib/icon-wrapper';
import { Table } from '@/components/application/table/table';

const SearchLg = faIcon(faMagnifyingGlass);
import { Badge } from '@/components/base/badges/badges';
import { Input } from '@/components/base/input/input';
import { Tabs, TabList, Tab } from '@/components/application/tabs/tabs';
import { PhoneActionCell } from './phone-action-cell';
import { formatPhone, formatTimeOnly, formatShortDate } from '@/lib/format';
import { notify } from '@/lib/toast';
import { cx } from '@/utils/cx';

type WorklistLead = {
    id: string;
    createdAt: string;
    contactName: { firstName: string; lastName: string } | null;
    contactPhone: { number: string; callingCode: string }[] | null;
    leadSource: string | null;
    leadStatus: string | null;
    interestedService: string | null;
    aiSummary: string | null;
    aiSuggestedAction: string | null;
    lastContacted: string | null;
    contactAttempts: number | null;
    utmCampaign: string | null;
    campaignId: string | null;
};

type WorklistFollowUp = {
    id: string;
    createdAt: string | null;
    followUpType: string | null;
    followUpStatus: string | null;
    scheduledAt: string | null;
    priority: string | null;
};

type MissedCall = {
    id: string;
    createdAt: string;
    callDirection: string | null;
    callerNumber: { number: string; callingCode: string }[] | null;
    startedAt: string | null;
    leadId: string | null;
    disposition: string | null;
    callbackstatus: string | null;
    callsourcenumber: string | null;
    missedcallcount: number | null;
    callbackattemptedat: string | null;
};

type MissedSubTab = 'pending' | 'attempted' | 'completed' | 'invalid';

interface WorklistPanelProps {
    missedCalls: MissedCall[];
    followUps: WorklistFollowUp[];
    leads: WorklistLead[];
    loading: boolean;
    onSelectLead: (lead: WorklistLead) => void;
    selectedLeadId: string | null;
    onDialMissedCall?: (missedCallId: string) => void;
}

type TabKey = 'all' | 'missed' | 'leads' | 'follow-ups';

type WorklistRow = {
    id: string;
    type: 'missed' | 'callback' | 'follow-up' | 'lead';
    priority: 'URGENT' | 'HIGH' | 'NORMAL' | 'LOW';
    name: string;
    phone: string;
    phoneRaw: string;
    direction: 'inbound' | 'outbound' | null;
    typeLabel: string;
    reason: string;
    createdAt: string;
    taskState: 'PENDING' | 'ATTEMPTED' | 'SCHEDULED';
    leadId: string | null;
    originalLead: WorklistLead | null;
    lastContactedAt: string | null;
    contactAttempts: number;
    source: string | null;
    lastDisposition: string | null;
    missedCallId: string | null;
};

const priorityConfig: Record<string, { color: 'error' | 'warning' | 'brand' | 'gray'; label: string; sort: number }> = {
    URGENT: { color: 'error', label: 'Urgent', sort: 0 },
    HIGH: { color: 'warning', label: 'High', sort: 1 },
    NORMAL: { color: 'brand', label: 'Normal', sort: 2 },
    LOW: { color: 'gray', label: 'Low', sort: 3 },
};

const followUpLabel: Record<string, string> = {
    CALLBACK: 'Callback',
    APPOINTMENT_REMINDER: 'Appt Reminder',
    POST_VISIT: 'Post-visit',
    MARKETING: 'Marketing',
    REVIEW_REQUEST: 'Review',
};

const computeSla = (dateStr: string): { label: string; color: 'success' | 'warning' | 'error' } => {
    const minutes = Math.max(0, Math.round((Date.now() - new Date(dateStr).getTime()) / 60000));
    if (minutes < 1) return { label: '<1m', color: 'success' };
    if (minutes < 15) return { label: `${minutes}m`, color: 'success' };
    if (minutes < 30) return { label: `${minutes}m`, color: 'warning' };
    if (minutes < 60) return { label: `${minutes}m`, color: 'error' };
    const hours = Math.floor(minutes / 60);
    if (hours < 24) return { label: `${hours}h ${minutes % 60}m`, color: 'error' };
    return { label: `${Math.floor(hours / 24)}d`, color: 'error' };
};

const formatTimeAgo = (dateStr: string): string => {
    const minutes = Math.round((Date.now() - new Date(dateStr).getTime()) / 60000);
    if (minutes < 1) return 'Just now';
    if (minutes < 60) return `${minutes}m ago`;
    const hours = Math.floor(minutes / 60);
    if (hours < 24) return `${hours}h ago`;
    return `${Math.floor(hours / 24)}d ago`;
};

const formatDisposition = (disposition: string): string =>
    disposition.replace(/_/g, ' ').replace(/\b\w/g, c => c.toUpperCase());

const formatSource = (source: string): string => {
    const map: Record<string, string> = {
        FACEBOOK_AD: 'Facebook',
        GOOGLE_AD: 'Google',
        WALK_IN: 'Walk-in',
        REFERRAL: 'Referral',
        WEBSITE: 'Website',
        PHONE_INQUIRY: 'Phone',
    };
    return map[source] ?? source.replace(/_/g, ' ');
};

const IconInbound = faIcon(faPhoneArrowDown);
const IconOutbound = faIcon(faPhoneArrowUp);

const buildRows = (missedCalls: MissedCall[], followUps: WorklistFollowUp[], leads: WorklistLead[]): WorklistRow[] => {
    const rows: WorklistRow[] = [];

    for (const call of missedCalls) {
        const phone = call.callerNumber?.[0];
        const countBadge = call.missedcallcount && call.missedcallcount > 1 ? ` (${call.missedcallcount}x)` : '';
        const sourceSuffix = call.callsourcenumber ? ` • ${call.callsourcenumber}` : '';
        rows.push({
            id: `mc-${call.id}`,
            type: 'missed',
            priority: 'HIGH',
            name: (phone ? formatPhone(phone) : 'Unknown') + countBadge,
            phone: phone ? formatPhone(phone) : '',
            phoneRaw: phone?.number ?? '',
            direction: call.callDirection === 'OUTBOUND' ? 'outbound' : 'inbound',
            typeLabel: 'Missed Call',
            reason: call.startedAt
                ? `Missed at ${formatTimeOnly(call.startedAt)}${sourceSuffix}`
                : 'Missed call',
            createdAt: call.createdAt,
            taskState: call.callbackstatus === 'CALLBACK_ATTEMPTED' ? 'ATTEMPTED' : 'PENDING',
            leadId: call.leadId,
            originalLead: null,
            lastContactedAt: call.callbackattemptedat ?? call.startedAt ?? call.createdAt,
            contactAttempts: 0,
            source: call.callsourcenumber ?? null,
            lastDisposition: call.disposition ?? null,
            missedCallId: call.id,
        });
    }

    for (const fu of followUps) {
        const isOverdue = fu.followUpStatus === 'OVERDUE' || (fu.scheduledAt !== null && new Date(fu.scheduledAt) < new Date());
        const label = followUpLabel[fu.followUpType ?? ''] ?? fu.followUpType ?? 'Follow-up';
        rows.push({
            id: `fu-${fu.id}`,
            type: fu.followUpType === 'CALLBACK' ? 'callback' : 'follow-up',
            priority: (fu.priority as WorklistRow['priority']) ?? (isOverdue ? 'HIGH' : 'NORMAL'),
            name: label,
            phone: '',
            phoneRaw: '',
            direction: null,
            typeLabel: fu.followUpType === 'CALLBACK' ? 'Callback' : 'Follow-up',
            reason: fu.scheduledAt
                ? `Scheduled ${formatShortDate(fu.scheduledAt)}`
                : '',
            createdAt: fu.createdAt ?? fu.scheduledAt ?? new Date().toISOString(),
            taskState: isOverdue ? 'PENDING' : (fu.followUpStatus === 'COMPLETED' ? 'ATTEMPTED' : 'SCHEDULED'),
            leadId: null,
            originalLead: null,
            lastContactedAt: fu.scheduledAt ?? fu.createdAt ?? null,
            contactAttempts: 0,
            source: null,
            lastDisposition: null,
            missedCallId: null,
        });
    }

    for (const lead of leads) {
        const firstName = lead.contactName?.firstName ?? '';
        const lastName = lead.contactName?.lastName ?? '';
        const fullName = `${firstName} ${lastName}`.trim() || 'Unknown';
        const phone = lead.contactPhone?.[0];
        rows.push({
            id: `lead-${lead.id}`,
            type: 'lead',
            priority: 'NORMAL',
            name: fullName,
            phone: phone ? formatPhone(phone) : '',
            phoneRaw: phone?.number ?? '',
            direction: null,
            typeLabel: 'Lead',
            reason: lead.interestedService ?? lead.aiSuggestedAction ?? '',
            createdAt: lead.createdAt,
            taskState: 'PENDING',
            leadId: lead.id,
            originalLead: lead,
            lastContactedAt: lead.lastContacted ?? null,
            contactAttempts: lead.contactAttempts ?? 0,
            source: lead.leadSource ?? lead.utmCampaign ?? null,
            lastDisposition: null,
            missedCallId: null,
        });
    }

    // Remove rows without a phone number — agent can't act on them
    const actionableRows = rows.filter(r => r.phoneRaw);

    actionableRows.sort((a, b) => {
        const pa = priorityConfig[a.priority]?.sort ?? 2;
        const pb = priorityConfig[b.priority]?.sort ?? 2;
        if (pa !== pb) return pa - pb;
        return new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime();
    });

    return actionableRows;
};

export const WorklistPanel = ({ missedCalls, followUps, leads, loading, onSelectLead, selectedLeadId, onDialMissedCall }: WorklistPanelProps) => {
    const [tab, setTab] = useState<TabKey>('all');
    const [search, setSearch] = useState('');
    const [missedSubTab, setMissedSubTab] = useState<MissedSubTab>('pending');
    const [sortDescriptor, setSortDescriptor] = useState<SortDescriptor>({ column: 'sla', direction: 'descending' });

    const missedByStatus = useMemo(() => ({
        pending: missedCalls.filter(c => c.callbackstatus === 'PENDING_CALLBACK' || !c.callbackstatus),
        attempted: missedCalls.filter(c => c.callbackstatus === 'CALLBACK_ATTEMPTED'),
        completed: missedCalls.filter(c => c.callbackstatus === 'CALLBACK_COMPLETED' || c.callbackstatus === 'WRONG_NUMBER'),
        invalid: missedCalls.filter(c => c.callbackstatus === 'INVALID'),
    }), [missedCalls]);

    const allRows = useMemo(
        () => buildRows(missedCalls, followUps, leads),
        [missedCalls, followUps, leads],
    );

    // Build rows from sub-tab filtered missed calls when on missed tab
    const missedSubTabRows = useMemo(
        () => buildRows(missedByStatus[missedSubTab], [], []),
        [missedByStatus, missedSubTab],
    );

    const filteredRows = useMemo(() => {
        let rows = allRows;
        if (tab === 'missed') rows = missedSubTabRows;
        else if (tab === 'leads') rows = rows.filter((r) => r.type === 'lead');
        else if (tab === 'follow-ups') rows = rows.filter((r) => r.type === 'follow-up');

        if (search.trim()) {
            const q = search.toLowerCase();
            rows = rows.filter(
                (r) => r.name.toLowerCase().includes(q) || r.phone.toLowerCase().includes(q) || r.phoneRaw.includes(q),
            );
        }

        if (sortDescriptor.column) {
            const dir = sortDescriptor.direction === 'ascending' ? 1 : -1;
            rows = [...rows].sort((a, b) => {
                switch (sortDescriptor.column) {
                    case 'priority': {
                        const pa = priorityConfig[a.priority]?.sort ?? 2;
                        const pb = priorityConfig[b.priority]?.sort ?? 2;
                        return (pa - pb) * dir;
                    }
                    case 'name':
                        return a.name.localeCompare(b.name) * dir;
                    case 'sla': {
                        const ta = new Date(a.lastContactedAt ?? a.createdAt).getTime();
                        const tb = new Date(b.lastContactedAt ?? b.createdAt).getTime();
                        return (ta - tb) * dir;
                    }
                    default:
                        return 0;
                }
            });
        }

        return rows;
    }, [allRows, tab, search, sortDescriptor, missedSubTabRows]);

    const missedCount = allRows.filter((r) => r.type === 'missed').length;
    const leadCount = allRows.filter((r) => r.type === 'lead').length;
    const followUpCount = allRows.filter((r) => r.type === 'follow-up').length;

    // Notification for new missed calls
    const prevMissedCount = useRef(missedCount);
    useEffect(() => {
        if (missedCount > prevMissedCount.current && prevMissedCount.current > 0) {
            notify.info('New Missed Call', `${missedCount - prevMissedCount.current} new missed call(s)`);
        }
        prevMissedCount.current = missedCount;
    }, [missedCount]);

    const PAGE_SIZE = 15;
    const [page, setPage] = useState(1);

    const handleTabChange = useCallback((key: TabKey) => { setTab(key); setPage(1); }, []);
    const handleSearch = useCallback((value: string) => { setSearch(value); setPage(1); }, []);

    const totalPages = Math.max(1, Math.ceil(filteredRows.length / PAGE_SIZE));
    const pagedRows = filteredRows.slice((page - 1) * PAGE_SIZE, page * PAGE_SIZE);

    const tabItems = [
        { id: 'all' as const, label: 'All Tasks', badge: allRows.length > 0 ? String(allRows.length) : undefined },
        { id: 'missed' as const, label: 'Missed Calls', badge: missedCount > 0 ? String(missedCount) : undefined },
        { id: 'leads' as const, label: 'Leads', badge: leadCount > 0 ? String(leadCount) : undefined },
        { id: 'follow-ups' as const, label: 'Follow-ups', badge: followUpCount > 0 ? String(followUpCount) : undefined },
    ];

    if (loading) {
        return (
            <div className="flex items-center justify-center py-12">
                <p className="text-sm text-tertiary">Loading worklist...</p>
            </div>
        );
    }

    const isEmpty = missedCalls.length === 0 && followUps.length === 0 && leads.length === 0;

    if (isEmpty) {
        return (
            <div className="flex flex-col items-center justify-center py-12 text-center">
                <p className="text-sm font-semibold text-primary">All clear</p>
                <p className="text-xs text-tertiary mt-1">No pending items in your worklist</p>
            </div>
        );
    }

    return (
        <div className="flex flex-1 flex-col min-h-0 overflow-hidden">
            {/* Filter tabs + search */}
            <div className="flex shrink-0 items-end justify-between border-b border-secondary px-5 pt-3 pb-0.5">
                <Tabs selectedKey={tab} onSelectionChange={(key) => handleTabChange(key as TabKey)}>
                    <TabList items={tabItems} type="underline" size="sm">
                        {(item) => <Tab key={item.id} id={item.id} label={item.label} badge={item.badge} />}
                    </TabList>
                </Tabs>
                <div className="w-44 shrink-0">
                    <Input
                        placeholder="Search..."
                        icon={SearchLg}
                        size="sm"
                        value={search}
                        onChange={handleSearch}
                        aria-label="Search worklist"
                    />
                </div>
            </div>

            {/* Missed call status sub-tabs */}
            {tab === 'missed' && (
                <div className="flex shrink-0 gap-1 px-5 py-2 border-b border-secondary">
                    {(['pending', 'attempted', 'completed', 'invalid'] as MissedSubTab[]).map(sub => (
                        <button
                            key={sub}
                            onClick={() => { setMissedSubTab(sub); setPage(1); }}
                            className={cx(
                                'px-3 py-1 text-xs font-medium rounded-md capitalize transition duration-100 ease-linear',
                                missedSubTab === sub
                                    ? 'bg-brand-50 text-brand-700 border border-brand-200'
                                    : 'text-tertiary hover:text-secondary hover:bg-secondary',
                            )}
                        >
                            {sub}
                            {sub === 'pending' && missedByStatus.pending.length > 0 && (
                                <span className="ml-1.5 bg-error-50 text-error-700 text-xs px-1.5 py-0.5 rounded-full">
                                    {missedByStatus.pending.length}
                                </span>
                            )}
                        </button>
                    ))}
                </div>
            )}

            {filteredRows.length === 0 ? (
                <div className="flex items-center justify-center py-12">
                    <p className="text-sm text-quaternary">
                        {search ? 'No matching items' : 'No items in this category'}
                    </p>
                </div>
            ) : (
                <div className="flex flex-1 flex-col min-h-0 overflow-hidden px-2 pt-3">
                <Table size="sm" sortDescriptor={sortDescriptor} onSortChange={setSortDescriptor}>
                    <Table.Header>
                        <Table.Head id="priority" label="PRIORITY" className="w-20" isRowHeader allowsSorting />
                        <Table.Head id="name" label="PATIENT" allowsSorting />
                        <Table.Head label="PHONE" />
                        <Table.Head label={tab === 'missed' ? 'BRANCH' : 'SOURCE'} className="w-28" />
                        <Table.Head id="sla" label="SLA" className="w-24" allowsSorting />
                    </Table.Header>
                    <Table.Body items={pagedRows}>
                        {(row) => {
                            const priority = priorityConfig[row.priority] ?? priorityConfig.NORMAL;
                            const sla = computeSla(row.lastContactedAt ?? row.createdAt);
                            const isSelected = row.originalLead !== null && row.originalLead.id === selectedLeadId;

                            // Sub-line: last interaction context
                            const subLine = row.lastContactedAt
                                ? `${formatTimeAgo(row.lastContactedAt)}${row.lastDisposition ? ` — ${formatDisposition(row.lastDisposition)}` : ''}`
                                : row.reason || row.typeLabel;

                            return (
                                <Table.Row
                                    id={row.id}
                                    className={cx(
                                        'cursor-pointer group/row',
                                        isSelected && 'bg-brand-primary',
                                    )}
                                    onAction={() => {
                                        if (row.originalLead) onSelectLead(row.originalLead);
                                    }}
                                >
                                    <Table.Cell>
                                        <Badge size="sm" color={priority.color} type="pill-color">
                                            {priority.label}
                                        </Badge>
                                    </Table.Cell>
                                    <Table.Cell>
                                        <div className="flex items-center gap-2">
                                            {row.direction === 'inbound' && (
                                                <IconInbound className="size-3.5 text-fg-success-secondary shrink-0" />
                                            )}
                                            {row.direction === 'outbound' && (
                                                <IconOutbound className="size-3.5 text-fg-brand-secondary shrink-0" />
                                            )}
                                            <div className="min-w-0">
                                                <span className="text-sm font-medium text-primary truncate block max-w-[180px]">
                                                    {row.name}
                                                </span>
                                                <span className="text-xs text-tertiary truncate block max-w-[200px]">
                                                    {subLine}
                                                </span>
                                            </div>
                                        </div>
                                    </Table.Cell>
                                    <Table.Cell>
                                        {row.phoneRaw ? (
                                            <PhoneActionCell
                                                phoneNumber={row.phoneRaw}
                                                displayNumber={row.phone}
                                                leadId={row.leadId ?? undefined}
                                                onDial={row.missedCallId ? () => onDialMissedCall?.(row.missedCallId!) : undefined}
                                            />
                                        ) : (
                                            <span className="text-xs text-quaternary italic">No phone</span>
                                        )}
                                    </Table.Cell>
                                    <Table.Cell>
                                        {row.source ? (
                                            <span className="text-xs text-tertiary truncate block max-w-[100px]">
                                                {formatSource(row.source)}
                                            </span>
                                        ) : (
                                            <span className="text-xs text-quaternary">—</span>
                                        )}
                                    </Table.Cell>
                                    <Table.Cell>
                                        <Badge size="sm" color={sla.color} type="pill-color">
                                            {sla.label}
                                        </Badge>
                                    </Table.Cell>
                                </Table.Row>
                            );
                        }}
                    </Table.Body>
                </Table>
                {totalPages > 1 && (
                    <div className="flex shrink-0 items-center justify-between border-t border-secondary px-5 py-3">
                        <span className="text-xs text-tertiary">
                            Showing {(page - 1) * PAGE_SIZE + 1}–{Math.min(page * PAGE_SIZE, filteredRows.length)} of {filteredRows.length}
                        </span>
                        <div className="flex items-center gap-1">
                            <button
                                onClick={() => setPage(Math.max(1, page - 1))}
                                disabled={page === 1}
                                className="px-2 py-1 text-xs font-medium text-secondary rounded-md hover:bg-primary_hover disabled:text-disabled disabled:cursor-not-allowed transition duration-100 ease-linear"
                            >
                                Previous
                            </button>
                            {Array.from({ length: totalPages }, (_, i) => i + 1).map((p) => (
                                <button
                                    key={p}
                                    onClick={() => setPage(p)}
                                    className={cx(
                                        "size-8 text-xs font-medium rounded-lg transition duration-100 ease-linear",
                                        p === page ? "bg-active text-brand-secondary" : "text-tertiary hover:bg-primary_hover",
                                    )}
                                >
                                    {p}
                                </button>
                            ))}
                            <button
                                onClick={() => setPage(Math.min(totalPages, page + 1))}
                                disabled={page === totalPages}
                                className="px-2 py-1 text-xs font-medium text-secondary rounded-md hover:bg-primary_hover disabled:text-disabled disabled:cursor-not-allowed transition duration-100 ease-linear"
                            >
                                Next
                            </button>
                        </div>
                    </div>
                )}
                </div>
            )}
        </div>
    );
};

export type { WorklistLead };
