"use client";

import React, { createContext, useContext, useEffect, useMemo, useState } from "react";
import { api } from "@/lib/api";

export interface AppNotification {
  id: number;
  title: string;
  message: string;
  time: string;
  isRead: boolean;
  type?: "info" | "success" | "warning";
  url?: string | null;
  image_url?: string | null;
}

interface NotificationsContextType {
  notifications: AppNotification[];
  unreadCount: number;
  markAllRead: () => void;
  markRead: (id: number) => void;
  add: (n: Omit<AppNotification, "id" | "isRead">) => void;
  clear: () => void;
}

const NotificationsContext = createContext<NotificationsContextType | undefined>(undefined);

function timeAgo(iso?: string): string {
  if (!iso) return "";
  const then = new Date(iso).getTime();
  const now = Date.now();
  const diff = Math.max(0, Math.floor((now - then) / 1000));
  if (diff < 60) return `${diff}s ago`;
  if (diff < 3600) return `${Math.floor(diff / 60)} mins ago`;
  if (diff < 86400) return `${Math.floor(diff / 3600)} hours ago`;
  return `${Math.floor(diff / 86400)} days ago`;
}

export function NotificationsProvider({ children }: { children: React.ReactNode }) {
  const [list, setList] = useState<AppNotification[]>([]);
  const [ready, setReady] = useState(false);
  const [readIds, setReadIds] = useState<number[]>([]);

  // Load read ids from storage
  useEffect(() => {
    try {
      const raw = localStorage.getItem("notifications_read_ids");
      if (raw) {
        const ids = JSON.parse(raw);
        if (Array.isArray(ids)) setReadIds(ids.filter((n: any) => typeof n === "number"));
      }
    } catch {}
  }, []);

  // Initial fetch from backend
  useEffect(() => {
    const load = async () => {
      try {
        const res = await api.getNotifications(20);
        const items = (res as any)?.data || [];
        const mapped: AppNotification[] = items.map((n: any) => ({
          id: Number(n.id),
          title: String(n.title || "Notification"),
          message: String(n.message || ""),
          time: timeAgo(n.created_at),
          isRead: readIds.includes(Number(n.id)),
          type: (n.type as any) || "info",
          url: n.url || null,
          image_url: n.image_url || null,
        }));
        setList(mapped);
      } catch {
        setList([]);
      } finally {
        setReady(true);
      }
    };
    load();
  }, []); // eslint-disable-line react-hooks/exhaustive-deps

  // OneSignal live updates
  useEffect(() => {
    if (typeof window === "undefined") return;
    const attach = () => {
      if (!("OneSignal" in window) || !window.OneSignal) return;
      window.OneSignal.push(function () {
        try {
          window.OneSignal.on('notificationDisplay', function (event: any) {
            const title = event?.heading || event?.payload?.headings?.en || "Notification";
            const message = event?.content || event?.payload?.body || event?.payload?.contents?.en || "";
            const time = timeAgo(new Date().toISOString());
            setList(prev => [{ id: Date.now(), title, message, time, isRead: false, type: "info" }, ...prev]);
          });
        } catch {}
      });
    };
    const t = setTimeout(attach, 1000);
    return () => clearTimeout(t);
  }, []);

  // Persist read ids
  useEffect(() => {
    try {
      localStorage.setItem("notifications_read_ids", JSON.stringify(readIds));
    } catch {}
  }, [readIds]);

  const markAllRead = () => {
    setList(prev => prev.map(n => ({ ...n, isRead: true })));
    setReadIds(prev => {
      const all = [...new Set([...prev, ...list.map(n => n.id)])];
      return all;
    });
  };
  const markRead = (id: number) => {
    setList(prev => prev.map(n => (n.id === id ? { ...n, isRead: true } : n)));
    setReadIds(prev => (prev.includes(id) ? prev : [...prev, id]));
  };
  const add = (n: Omit<AppNotification, "id" | "isRead">) => setList(prev => [{ id: Date.now(), isRead: false, ...n }, ...prev]);
  const clear = () => setList([]);
  const unreadCount = useMemo(() => list.filter(n => !n.isRead).length, [list]);

  const value = useMemo(() => ({ notifications: list, unreadCount, markAllRead, markRead, add, clear }), [list, unreadCount]);
  return <NotificationsContext.Provider value={value}>{children}</NotificationsContext.Provider>;
}

export function useNotifications() {
  const ctx = useContext(NotificationsContext);
  if (!ctx) throw new Error("useNotifications must be used within a NotificationsProvider");
  return ctx;
}
