import { router, usePage } from '@inertiajs/react';
import {
    Bell, BellRing, CheckCheck, ListChecks, Loader2, MailOpen, Trash2, X,
} from 'lucide-react';
import Pusher from 'pusher-js';
import { useEffect, useRef, useState } from 'react';
import { useConfirm } from '@/Components/ConfirmDialog';
import BildirimIzinModal from '@/Components/BildirimIzinModal';
import { useGorevModal } from '@/Components/GorevModalProvider';
import { useProjeModal } from '@/Components/ProjeModalProvider';
import { useModulModal } from '@/Components/ModulModalProvider';
import { pushAbonele, pushDestekleniyor } from '@/lib/webpush';

/**
 * Pusher singleton — Inertia SPA'da sayfa geçişlerinde tek bir WebSocket bağlantısı yeterli.
 * Her component remount'unda yeni instance yaratıp eskisini disconnect etmek
 * "WebSocket already in CLOSING/CLOSED state" hatasına sebep oluyordu.
 */
let _pusherInstance: Pusher | null = null;
function pusherAl(key: string, cluster: string): Pusher {
    if (_pusherInstance) return _pusherInstance;
    _pusherInstance = new Pusher(key, { cluster, forceTLS: true });
    return _pusherInstance;
}

interface Bildirim {
    id: number;
    tip: string;
    baslik: string;
    mesaj?: string | null;
    link?: string | null;
    okundu_at?: string | null;
    created_at: string;
}

const TIP_IKON: Record<string, any> = {
    gorev_atama:    ListChecks,
    gorev_durum:    ListChecks,
    proje:          ListChecks,
    proje_durum:    ListChecks,
    proje_atama:    ListChecks,
    teklif:         ListChecks,
    randevu_atama:  ListChecks,
    randevu_olusturma: ListChecks,
    randevu_durum:  ListChecks,
    randevu_tarih:  ListChecks,
    teknik_servis:  ListChecks,
    genel:          Bell,
};

function zamanFarki(iso: string): string {
    const t = new Date(iso).getTime();
    const fark = Math.floor((Date.now() - t) / 1000);
    if (fark < 60) return 'şimdi';
    if (fark < 3600) return `${Math.floor(fark / 60)} dk önce`;
    if (fark < 86400) return `${Math.floor(fark / 3600)} sa önce`;
    if (fark < 604800) return `${Math.floor(fark / 86400)} gün önce`;
    return new Date(iso).toLocaleDateString('tr-TR');
}

export default function BildirimDropdown() {
    const props = usePage().props as any;
    const init = props.bildirim_init;
    const pusherConf = props.pusher;
    const vapidPublic: string = props.webpush?.vapid_public ?? '';
    const confirm = useConfirm();
    const gorevModal = useGorevModal();
    const projeModal = useProjeModal();
    const modulModal = useModulModal();

    const [acik, setAcik] = useState(false);
    const [bildirimler, setBildirimler] = useState<Bildirim[]>(init?.son_liste ?? []);
    const [okunmamis, setOkunmamis] = useState<number>(init?.okunmamis ?? 0);
    const [yukleniyor, setYukleniyor] = useState(false);
    const [yeniBildirim, setYeniBildirim] = useState(false); // bell animasyonu için
    const [bildirimIzni, setBildirimIzni] = useState<NotificationPermission>(
        typeof Notification !== 'undefined' ? Notification.permission : 'denied'
    );
    const [izinModalAcik, setIzinModalAcik] = useState(false);
    const dropdownRef = useRef<HTMLDivElement>(null);

    // Dış tıklamayla kapat
    useEffect(() => {
        if (!acik) return;
        const handler = (e: MouseEvent) => {
            if (dropdownRef.current && !dropdownRef.current.contains(e.target as Node)) {
                setAcik(false);
            }
        };
        document.addEventListener('mousedown', handler);
        return () => document.removeEventListener('mousedown', handler);
    }, [acik]);

    // Pusher subscribe — anlık bildirim alma
    useEffect(() => {
        if (!pusherConf?.key || !init?.kanal) return;

        const pusher = pusherAl(pusherConf.key, pusherConf.cluster || 'eu');
        const channel = pusher.subscribe(init.kanal);

        const handler = (data: Bildirim) => {
            setBildirimler((prev) => [data, ...prev].slice(0, 30));
            setOkunmamis((c) => c + 1);
            setYeniBildirim(true);
            setTimeout(() => setYeniBildirim(false), 3000);

            // Tarayıcı native bildirimi (sekme arka planda olsa bile pop-up çıkar)
            if (typeof Notification !== 'undefined' && Notification.permission === 'granted') {
                try {
                    const n = new Notification(data.baslik, {
                        body: data.mesaj ?? '',
                        tag: 'cari-takip-' + data.id,
                        icon: '/favicon.ico',
                        badge: '/favicon.ico',
                        // requireInteraction: true,  // istenirse kullanıcı kapatana kadar dursun
                    });
                    n.onclick = () => {
                        window.focus();
                        if (data.link) {
                            try { (window.location as any).href = data.link; } catch {}
                        }
                        n.close();
                    };
                } catch { /* bazı tarayıcılarda Notification ctor sınırlı; sessizce geç */ }
            }
        };
        channel.bind('yeni-bildirim', handler);

        // Cleanup: sadece bu handler'ı unbind et — singleton pusher disconnect EDİLMEZ.
        // Sayfa geçişlerinde aynı bağlantı korunur, WebSocket race condition'ı önlenir.
        return () => {
            channel.unbind('yeni-bildirim', handler);
        };
    }, [pusherConf?.key, pusherConf?.cluster, init?.kanal]);

    // Bildirim izni iste (ilk açılışta) ve state'i güncelle
    useEffect(() => {
        if (typeof Notification === 'undefined') return;
        setBildirimIzni(Notification.permission);
        if (Notification.permission === 'default') {
            Notification.requestPermission().then((p) => {
                setBildirimIzni(p);
                if (p === 'granted' && vapidPublic && pushDestekleniyor()) {
                    pushAbonele(vapidPublic).catch(() => {});
                }
            }).catch(() => {});
        } else if (Notification.permission === 'granted' && vapidPublic && pushDestekleniyor()) {
            // Zaten izin verilmiş → sessizce SW + abonelik kontrolünü yap
            pushAbonele(vapidPublic).catch(() => {});
        }
    // eslint-disable-next-line react-hooks/exhaustive-deps
    }, [vapidPublic]);

    // Manuel izin isteme (kullanıcı butona tıklarsa)
    const izinIste = () => {
        if (typeof Notification === 'undefined' || (typeof window !== 'undefined' && !window.isSecureContext)) {
            // HTTPS yok veya API yok — modal aç, kullanıcıya rehber göster
            setIzinModalAcik(true);
            return;
        }

        const mevcut = Notification.permission;

        // Reddedilmiş veya zaten granted ise direkt yardım modal'ı / sessizce çık
        if (mevcut === 'denied') {
            setIzinModalAcik(true);
            return;
        }
        if (mevcut === 'granted') {
            setBildirimIzni('granted');
            if (vapidPublic && pushDestekleniyor()) {
                pushAbonele(vapidPublic).catch(() => {});
            }
            return;
        }

        // default → izin iste. Promise yanıt vermezse 3sn sonra rehber modal'ı aç.
        let cevapGeldi = false;
        const zamanlayici = window.setTimeout(() => {
            if (!cevapGeldi && Notification.permission === 'default') {
                setIzinModalAcik(true);
            }
        }, 3000);

        const sonuca = (p: NotificationPermission) => {
            cevapGeldi = true;
            window.clearTimeout(zamanlayici);
            setBildirimIzni(p);
            if (p === 'granted') {
                try {
                    new Notification('Bildirimler etkinleştirildi', {
                        body: 'Artık burada anlık bildirim alacaksın.',
                        icon: '/favicon.ico',
                    });
                } catch (e) { /* sessiz */ }
                if (vapidPublic && pushDestekleniyor()) {
                    pushAbonele(vapidPublic).catch(() => {});
                }
            } else {
                // denied veya default → kullanıcıya rehber modal göster
                setIzinModalAcik(true);
            }
        };

        try {
            const r = Notification.requestPermission(sonuca);
            if (r && typeof (r as any).then === 'function') {
                (r as Promise<NotificationPermission>).then(sonuca).catch(() => {
                    cevapGeldi = true;
                    window.clearTimeout(zamanlayici);
                    setIzinModalAcik(true);
                });
            }
        } catch {
            cevapGeldi = true;
            window.clearTimeout(zamanlayici);
            setIzinModalAcik(true);
        }
    };

    const yenile = async () => {
        setYukleniyor(true);
        try {
            const r = await fetch('/bildirimler/', { credentials: 'same-origin', headers: { Accept: 'application/json' } });
            if (!r.ok) return; // 401/500 vb. — listeyi sıfırlama, eski state korunsun
            const ct = r.headers.get('content-type') || '';
            if (!ct.includes('application/json')) return; // HTML (login redirect) ise geç
            const data = await r.json();
            if (!data || !Array.isArray(data.bildirimler)) return; // beklenmedik şekil → koru
            const yeniListe = data.bildirimler;
            // Eğer backend boş döndüyse VE bizde dolu liste varsa: bir şey yanlış olabilir
            // (filtre / firma değişimi / cache). Mevcut listeyi sıfırlamayalım.
            if (yeniListe.length === 0 && bildirimler.length > 0) {
                // Sayı yine güncellensin (okundu olabilir)
                setOkunmamis(typeof data.okunmamis === 'number' ? data.okunmamis : okunmamis);
                return;
            }
            setBildirimler(yeniListe);
            setOkunmamis(typeof data.okunmamis === 'number' ? data.okunmamis : 0);
        } catch {
            // Network hatası — sessizce geç, listeyi koruyoruz
        } finally {
            setYukleniyor(false);
        }
    };

    const tikla = async (b: Bildirim) => {
        if (!b.okundu_at) {
            await fetch(`/bildirimler/${b.id}/oku/`, {
                method: 'POST',
                credentials: 'same-origin',
                headers: {
                    'X-CSRF-TOKEN': (document.querySelector('meta[name="csrf-token"]') as HTMLMetaElement)?.content ?? '',
                    'Accept': 'application/json',
                },
            });
            setBildirimler((prev) => prev.map((x) => x.id === b.id ? { ...x, okundu_at: new Date().toISOString() } : x));
            setOkunmamis((c) => Math.max(0, c - 1));
        }
        if (!b.link) return;

        // Çan'dan tıklamada SAYFA DEĞİŞMESİN — modal varsa yerinde aç.
        try {
            const url = new URL(b.link, window.location.origin);
            const gorevId = Number(url.searchParams.get('gorev'));
            if (gorevId > 0) { setAcik(false); gorevModal.gorevDuzenle(gorevId); return; }
            const projeId = Number(url.searchParams.get('proje'));
            if (projeId > 0) { setAcik(false); projeModal.projeDuzenle(projeId); return; }
            const teklifId = Number(url.searchParams.get('teklif'));
            if (teklifId > 0) { setAcik(false); modulModal.ac('teklif', teklifId); return; }
            const servisId = Number(url.searchParams.get('servis'));
            if (servisId > 0) { setAcik(false); modulModal.ac('servis', servisId); return; }
            const randevuId = Number(url.searchParams.get('randevu'));
            if (randevuId > 0) { setAcik(false); modulModal.ac('randevu', randevuId); return; }
        } catch { /* parse hatası ise düz visit */ }

        // Diğer tüm durumlar — normal navigate
        setAcik(false);
        router.visit(b.link);
    };

    const hepsiniOku = async () => {
        await fetch('/bildirimler/hepsini-oku/', {
            method: 'POST',
            credentials: 'same-origin',
            headers: {
                'X-CSRF-TOKEN': (document.querySelector('meta[name="csrf-token"]') as HTMLMetaElement)?.content ?? '',
                'Accept': 'application/json',
            },
        });
        const simdi = new Date().toISOString();
        setBildirimler((prev) => prev.map((x) => x.okundu_at ? x : { ...x, okundu_at: simdi }));
        setOkunmamis(0);
    };

    const sil = async (b: Bildirim, e: React.MouseEvent) => {
        e.stopPropagation();
        await fetch(`/bildirimler/${b.id}/`, {
            method: 'DELETE',
            credentials: 'same-origin',
            headers: {
                'X-CSRF-TOKEN': (document.querySelector('meta[name="csrf-token"]') as HTMLMetaElement)?.content ?? '',
                'Accept': 'application/json',
            },
        });
        setBildirimler((prev) => prev.filter((x) => x.id !== b.id));
        if (!b.okundu_at) setOkunmamis((c) => Math.max(0, c - 1));
    };

    const tumunuTemizle = async () => {
        const onay = await confirm({
            baslik: 'Bildirimleri Temizle',
            mesaj: <>Tüm bildirimler kalıcı olarak silinecek. Devam edilsin mi?</>,
            tip: 'tehlike',
            onayMetni: 'Tümünü Sil',
            iptalMetni: 'Vazgeç',
        });
        if (!onay) return;
        await fetch('/bildirimler/temizle/', {
            method: 'POST',
            credentials: 'same-origin',
            headers: {
                'X-CSRF-TOKEN': (document.querySelector('meta[name="csrf-token"]') as HTMLMetaElement)?.content ?? '',
                'Accept': 'application/json',
            },
        });
        setBildirimler([]);
        setOkunmamis(0);
    };

    return (
        <div className="relative" ref={dropdownRef}>
            <button
                type="button"
                onClick={() => { setAcik((v) => !v); if (!acik) yenile(); }}
                className={`relative inline-flex h-9 w-9 items-center justify-center rounded-lg border border-slate-200 bg-white text-slate-600 transition hover:bg-slate-50 ${yeniBildirim ? 'animate-pulse text-blue-600' : ''}`}
                aria-label="Bildirimler"
            >
                {yeniBildirim || okunmamis > 0 ? <BellRing className="h-5 w-5" /> : <Bell className="h-5 w-5" />}
                {okunmamis > 0 && (
                    <span className="absolute -right-0.5 -top-0.5 flex h-4 min-w-[16px] items-center justify-center rounded-full bg-rose-500 px-1 text-[10px] font-bold text-white ring-2 ring-white">
                        {okunmamis > 99 ? '99+' : okunmamis}
                    </span>
                )}
            </button>

            {acik && (
                <div className="fixed inset-x-2 top-[68px] z-50 max-h-[calc(100dvh-80px)] overflow-y-auto rounded-xl border border-slate-200 bg-white shadow-2xl sm:absolute sm:inset-x-auto sm:right-0 sm:top-auto sm:mt-2 sm:max-h-none sm:w-96 sm:max-w-[calc(100vw-2rem)] sm:overflow-visible">
                    {/* Tarayıcı bildirimi izin şeridi */}
                    {typeof Notification !== 'undefined' && bildirimIzni !== 'granted' && (
                        <div className={`flex items-center justify-between gap-2 border-b px-4 py-2 text-xs ${
                            bildirimIzni === 'denied'
                                ? 'border-amber-200 bg-amber-50 text-amber-900'
                                : 'border-blue-200 bg-blue-50 text-blue-900'
                        }`}>
                            <div className="flex items-center gap-1.5">
                                <BellRing className="h-3.5 w-3.5" />
                                <span>
                                    {bildirimIzni === 'denied'
                                        ? 'Tarayıcı bildirimi reddedildi. Adres çubuğundaki kilit ikonundan izin verebilirsin.'
                                        : 'Tarayıcı bildirimlerini aç — sekme arka planda olsa bile bildirim çıksın.'}
                                </span>
                            </div>
                            {bildirimIzni === 'default' && (
                                <button type="button" onClick={izinIste}
                                    className="flex-shrink-0 rounded-md bg-blue-600 px-2 py-1 text-[10px] font-semibold text-white hover:bg-blue-700">
                                    Etkinleştir
                                </button>
                            )}
                        </div>
                    )}

                    {/* Header */}
                    <div className="flex items-center justify-between border-b border-slate-200 px-4 py-3">
                        <div className="flex items-center gap-2">
                            <Bell className="h-4 w-4 text-slate-700" />
                            <h3 className="text-sm font-semibold text-slate-900">Bildirimler</h3>
                            {okunmamis > 0 && (
                                <span className="rounded-full bg-rose-100 px-2 py-0.5 text-[10px] font-semibold text-rose-700">
                                    {okunmamis} yeni
                                </span>
                            )}
                        </div>
                        {okunmamis > 0 && (
                            <button onClick={hepsiniOku} className="inline-flex items-center gap-1 text-xs font-medium text-blue-600 hover:text-blue-700">
                                <CheckCheck className="h-3 w-3" /> Tümünü oku
                            </button>
                        )}
                    </div>

                    {/* Liste */}
                    <div className="max-h-[400px] overflow-y-auto">
                        {yukleniyor ? (
                            <div className="flex h-32 items-center justify-center text-sm text-slate-500">
                                <Loader2 className="mr-2 h-4 w-4 animate-spin" /> Yükleniyor...
                            </div>
                        ) : bildirimler.length === 0 ? (
                            <div className="flex h-32 flex-col items-center justify-center text-center">
                                <MailOpen className="mb-2 h-8 w-8 text-slate-300" />
                                <div className="text-sm text-slate-500">Bildirim yok.</div>
                            </div>
                        ) : (
                            bildirimler.map((b) => {
                                const Icon = TIP_IKON[b.tip] ?? Bell;
                                const okunmamisMi = !b.okundu_at;
                                return (
                                    <div
                                        key={b.id}
                                        role="button"
                                        tabIndex={0}
                                        onClick={() => tikla(b)}
                                        onKeyDown={(e) => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); tikla(b); } }}
                                        className={`group flex w-full cursor-pointer items-start gap-3 border-b border-slate-100 px-4 py-3 text-left transition hover:bg-slate-50 ${okunmamisMi ? 'bg-blue-50/40' : ''}`}
                                    >
                                        <div className={`flex h-8 w-8 flex-shrink-0 items-center justify-center rounded-full ${okunmamisMi ? 'bg-blue-100 text-blue-700' : 'bg-slate-100 text-slate-500'}`}>
                                            <Icon className="h-4 w-4" />
                                        </div>
                                        <div className="min-w-0 flex-1">
                                            <div className="flex items-center gap-2">
                                                <div className={`text-sm ${okunmamisMi ? 'font-semibold text-slate-900' : 'font-medium text-slate-700'}`}>
                                                    {b.baslik}
                                                </div>
                                                {okunmamisMi && <span className="h-1.5 w-1.5 rounded-full bg-blue-500" />}
                                            </div>
                                            {b.mesaj && (
                                                <p className="mt-0.5 line-clamp-2 text-xs text-slate-600">{b.mesaj}</p>
                                            )}
                                            <p className="mt-1 text-[10px] text-slate-400">{zamanFarki(b.created_at)}</p>
                                        </div>
                                        <button
                                            type="button"
                                            onClick={(e) => sil(b, e)}
                                            className="rounded p-1 text-slate-400 opacity-0 transition hover:bg-rose-50 hover:text-rose-600 group-hover:opacity-100"
                                            title="Sil"
                                        >
                                            <X className="h-3.5 w-3.5" />
                                        </button>
                                    </div>
                                );
                            })
                        )}
                    </div>

                    {/* Footer */}
                    {bildirimler.length > 0 && (
                        <div className="flex items-center justify-end border-t border-slate-200 px-4 py-2">
                            <button onClick={tumunuTemizle}
                                className="inline-flex items-center gap-1 text-xs font-medium text-slate-500 hover:text-rose-600">
                                <Trash2 className="h-3 w-3" /> Tümünü temizle
                            </button>
                        </div>
                    )}
                </div>
            )}

            <BildirimIzinModal
                open={izinModalAcik}
                onClose={() => setIzinModalAcik(false)}
                onTekrar={() => izinIste()}
            />
        </div>
    );
}
