'use client';

/**
 * Announcements Hook
 * 
 * Fetch and manage system announcements
 */

import { useState, useEffect, useCallback } from 'react';
import api from '../lib/api-client';

export interface Announcement {
  id: string;
  type: 'info' | 'warning' | 'success' | 'urgent';
  title: string;
  message: string;
  link?: string;
  linkText?: string;
  createdAt: string;
  expiresAt?: string;
  read: boolean;
  pinned?: boolean;
}

const ANNOUNCEMENTS_KEY = 'gcx_fshs_announcements';
const READ_IDS_KEY = 'gcx_fshs_announcements_read';
const DISMISSED_IDS_KEY = 'gcx_fshs_announcements_dismissed';

// Default system announcements (can be overridden by API)
const DEFAULT_ANNOUNCEMENTS: Announcement[] = [
  {
    id: 'welcome-2026',
    type: 'info',
    title: 'Welcome to GCX FSHS Field',
    message: 'Track deliveries, manage supplies, and stay connected with the school network.',
    createdAt: new Date().toISOString(),
    read: false,
    pinned: true,
  },
];

export function useAnnouncements() {
  const [announcements, setAnnouncements] = useState<Announcement[]>([]);
  const [isLoading, setIsLoading] = useState(true);
  const [readIds, setReadIds] = useState<Set<string>>(new Set());
  const [dismissedIds, setDismissedIds] = useState<Set<string>>(new Set());

  // Load read IDs from storage
  const loadReadIds = useCallback(() => {
    try {
      const stored = localStorage.getItem(READ_IDS_KEY);
      if (stored) {
        setReadIds(new Set(JSON.parse(stored)));
      }
      const dismissedStored = localStorage.getItem(DISMISSED_IDS_KEY);
      if (dismissedStored) {
        setDismissedIds(new Set(JSON.parse(dismissedStored)));
      }
    } catch {
      // Ignore errors
    }
  }, []);

  // Save read IDs to storage
  const saveReadIds = useCallback((ids: Set<string>) => {
    try {
      localStorage.setItem(READ_IDS_KEY, JSON.stringify(Array.from(ids)));
    } catch {
      // Ignore errors
    }
  }, []);

  // Save dismissed IDs to storage
  const saveDismissedIds = useCallback((ids: Set<string>) => {
    try {
      localStorage.setItem(DISMISSED_IDS_KEY, JSON.stringify(Array.from(ids)));
    } catch {
      // Ignore errors
    }
  }, []);

  // Fetch announcements
  const fetchAnnouncements = useCallback(async () => {
    setIsLoading(true);
    try {
      // Try to fetch from API
      const response = await api.get('/announcements').catch(() => null);
      
      let serverAnnouncements: Announcement[] = [];
      if (response?.data?.data) {
        serverAnnouncements = response.data.data;
      }

      // Merge with defaults
      const merged = [...serverAnnouncements];
      
      // Add defaults that aren't in server response
      DEFAULT_ANNOUNCEMENTS.forEach(def => {
        if (!merged.find(a => a.id === def.id)) {
          merged.push(def);
        }
      });

      // Filter out expired and dismissed
      const now = new Date();
      const active = merged.filter(a => {
        // Filter out dismissed
        if (dismissedIds.has(a.id)) {
          return false;
        }
        // Filter out expired
        if (a.expiresAt) {
          return new Date(a.expiresAt) > now;
        }
        return true;
      });

      // Mark read status
      const withReadStatus = active.map(a => ({
        ...a,
        read: readIds.has(a.id),
      }));

      // Sort: pinned first, then by date
      withReadStatus.sort((a, b) => {
        if (a.pinned && !b.pinned) return -1;
        if (!a.pinned && b.pinned) return 1;
        return new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime();
      });

      setAnnouncements(withReadStatus);
    } catch (error) {
      console.error('Failed to fetch announcements:', error);
      // Use defaults on error
      setAnnouncements(DEFAULT_ANNOUNCEMENTS.map(a => ({ ...a, read: readIds.has(a.id) })));
    } finally {
      setIsLoading(false);
    }
  }, [readIds, dismissedIds]);

  // Mark announcement as read
  const markAsRead = useCallback((id: string) => {
    const newReadIds = new Set(readIds);
    newReadIds.add(id);
    setReadIds(newReadIds);
    saveReadIds(newReadIds);

    setAnnouncements(prev =>
      prev.map(a => (a.id === id ? { ...a, read: true } : a))
    );
  }, [readIds, saveReadIds]);

  // Mark all as read
  const markAllAsRead = useCallback(() => {
    const newReadIds = new Set(readIds);
    announcements.forEach(a => newReadIds.add(a.id));
    setReadIds(newReadIds);
    saveReadIds(newReadIds);

    setAnnouncements(prev => prev.map(a => ({ ...a, read: true })));
  }, [announcements, readIds, saveReadIds]);

  // Dismiss announcement (mark as read and hide)
  const dismiss = useCallback((id: string) => {
    // Add to dismissed set
    const newDismissedIds = new Set(dismissedIds);
    newDismissedIds.add(id);
    setDismissedIds(newDismissedIds);
    saveDismissedIds(newDismissedIds);
    
    // Also mark as read
    markAsRead(id);
    
    // Remove from visible announcements immediately
    setAnnouncements(prev => prev.filter(a => a.id !== id));
  }, [dismissedIds, saveDismissedIds, markAsRead]);

  // Initialize
  useEffect(() => {
    loadReadIds();
  }, [loadReadIds]);

  useEffect(() => {
    fetchAnnouncements();
  }, [fetchAnnouncements]);

  const unreadCount = announcements.filter(a => !a.read).length;
  const urgentAnnouncements = announcements.filter(a => a.type === 'urgent' && !a.read);

  return {
    announcements,
    unreadCount,
    urgentAnnouncements,
    isLoading,
    markAsRead,
    markAllAsRead,
    dismiss,
    refresh: fetchAnnouncements,
  };
}
