import * as DM from '@radix-ui/react-dropdown-menu';
import { router } from '@inertiajs/react';
import { Bell, CheckCheck, Eye, FileSignature, MailOpen, MessageCircle, XCircle } from 'lucide-react';
import { useCallback, useEffect, useState } from 'react';
import { dateTime } from '@/lib/format';
import { http } from '@/lib/http';
import { cn } from '@/lib/utils';

type Item = { id: string; read: boolean; at: string; event: string | null; message: string; detail: string | null; quote_id: number | null; company_id: number | null; url?: string | null };
const ICONS: Record<string, typeof Bell> = { first_email_open: MailOpen, first_view: Eye, repeat_views: Eye, question: MessageCircle, accepted: FileSignature, declined: XCircle, bounced: XCircle };

/** Header bell: polls every 30 s while the tab is visible (no websockets needed). */
export function NotificationBell({ activeCompanyId }: { activeCompanyId: number }) {
    const [data, setData] = useState<{ unread: number; items: Item[] }>({ unread: 0, items: [] });
    const load = useCallback(() => { http<{ unread: number; items: Item[] }>('GET', '/api/notifications').then(setData).catch(() => {}); }, []);
    useEffect(() => {
        load();
        const t = window.setInterval(() => { if (document.visibilityState === 'visible') load(); }, 30000);
        return () => window.clearInterval(t);
    }, [load]);

    const open = async (n: Item) => {
        if (!n.read) await http('POST', '/api/notifications/read', { id: n.id }).catch(() => {});
        if (!n.quote_id && !n.url) return load();
        const url = n.url ?? `/quotes/${n.quote_id}/edit`;
        if (n.company_id && n.company_id !== activeCompanyId) {
            await http('POST', '/api/companies/switch', { company_id: n.company_id }).catch(() => {});
            window.location.href = url;
        } else router.visit(url);
    };
    const readAll = async () => { await http('POST', '/api/notifications/read', {}); load(); };

    return (
        <DM.Root onOpenChange={(o) => o && load()}>
            <DM.Trigger className="relative rounded-[5px] p-2 text-ink outline-none hover:bg-accent-soft hover:text-link focus-visible:ring-3 focus-visible:ring-accent-ring"
                aria-label={data.unread ? `Notifications, ${data.unread} unread` : 'Notifications'} data-testid="notification-bell">
                <Bell className="h-5 w-5" strokeWidth={1.75} />
                {data.unread > 0 && <span className="absolute right-1 top-1 flex h-4 min-w-4 items-center justify-center rounded-full bg-danger px-1 text-[10px] font-semibold text-white" data-testid="notification-count">{data.unread > 9 ? '9+' : data.unread}</span>}
            </DM.Trigger>
            <DM.Portal>
                <DM.Content align="end" sideOffset={8} className="motion-pop z-50 w-[22rem] max-w-[calc(100vw-1rem)] rounded-[var(--radius-card)] border border-line bg-surface p-1.5 shadow-pop">
                    <div className="flex items-center justify-between px-2.5 py-1.5">
                        <span className="text-sm font-semibold">Notifications</span>
                        {data.unread > 0 && <button type="button" onClick={readAll} className="inline-flex items-center gap-1 text-xs text-link hover:underline"><CheckCheck className="h-3.5 w-3.5" /> Mark all read</button>}
                    </div>
                    <div className="max-h-[60vh] overflow-y-auto">
                        {data.items.length === 0 && <p className="px-2.5 py-6 text-center text-sm text-ink-muted">You're all caught up.</p>}
                        {data.items.map((n) => {
                            const Icon = ICONS[n.event ?? ''] ?? Bell;
                            return (
                                <DM.Item key={n.id} onSelect={() => open(n)} data-testid="notification-item"
                                    className={cn('flex cursor-pointer gap-2.5 rounded-[5px] px-2.5 py-2 text-sm outline-none data-[highlighted]:bg-accent-soft', !n.read && 'bg-accent-soft/50')}>
                                    <Icon className="mt-0.5 h-4 w-4 shrink-0 text-link" />
                                    <span className="min-w-0">
                                        <span className={cn('block', !n.read && 'font-medium')}>{n.message}</span>
                                        {n.detail && <span className="block truncate text-xs text-ink-muted">{n.detail}</span>}
                                        <span className="block text-xs text-ink-muted">{dateTime(n.at)}</span>
                                    </span>
                                </DM.Item>
                            );
                        })}
                    </div>
                </DM.Content>
            </DM.Portal>
        </DM.Root>
    );
}
