// composables/useEvents.ts
import type { Event, EventsResponse, EventFilters, EventCreateRequest, EventRSVPRequest } from '~/utils/types';

export const useEvents = () => {
  const events = ref<Event[]>([]);
  const loading = ref(false);
  const error = ref<string | null>(null);
  const upcomingEvent = ref<Event | null>(null);
  const cache = reactive<Map<string, { data: Event[]; timestamp: number }>>(new Map());
  const CACHE_TIMEOUT = 5 * 60 * 1000; // 5 minutes

  // Get authenticated user info
  const { user, userTier } = useAuth();

  /**
   * Fetch events with optional filtering and caching
   */
  const fetchEvents = async (filters?: EventFilters & { force?: boolean }) => {
    loading.value = true;
    error.value = null;

    try {
      // Create cache key
      const cacheKey = JSON.stringify(filters || {});
      const cached = cache.get(cacheKey);
      
      // Check cache if not forcing refresh
      if (!filters?.force && cached) {
        const now = Date.now();
        if (now - cached.timestamp < CACHE_TIMEOUT) {
          events.value = cached.data;
          loading.value = false;
          return cached.data;
        }
      }

      // Default date range (current month + 2 months ahead)
      const defaultFilters: EventFilters = {
        start_date: startOfMonth(new Date()).toISOString(),
        end_date: endOfMonth(addMonths(new Date(), 2)).toISOString(),
        user_role: userTier.value,
        ...filters
      };

      const response = await $fetch<EventsResponse>('/api/events', {
        query: {
          ...defaultFilters,
          calendar_format: 'false'
        }
      });

      if (response.success) {
        events.value = response.data;
        
        // Cache the results
        cache.set(cacheKey, {
          data: response.data,
          timestamp: Date.now()
        });

        // Update upcoming event
        updateUpcomingEvent(response.data);
        
        return response.data;
      } else {
        throw new Error(response.message || 'Failed to fetch events');
      }
    } catch (err: any) {
      error.value = err.message || 'Failed to load events';
      console.error('Error fetching events:', err);
      throw err;
    } finally {
      loading.value = false;
    }
  };

  /**
   * Create a new event (board/admin only)
   */
  const createEvent = async (eventData: EventCreateRequest) => {
    loading.value = true;
    error.value = null;

    try {
      const response = await $fetch<{ success: boolean; data: Event; message: string }>('/api/events', {
        method: 'POST',
        body: eventData
      });

      if (response.success) {
        // Clear cache and refresh events
        cache.clear();
        await fetchEvents({ force: true });
        
        return response.data;
      } else {
        throw new Error(response.message || 'Failed to create event');
      }
    } catch (err: any) {
      error.value = err.message || 'Failed to create event';
      console.error('Error creating event:', err);
      throw err;
    } finally {
      loading.value = false;
    }
  };

  /**
   * RSVP to an event with support for guests and real-time updates
   */
  const rsvpToEvent = async (eventId: string, rsvpData: Omit<EventRSVPRequest, 'event_id'> & { extra_guests?: string }) => {
    loading.value = true;
    error.value = null;

    try {
      console.log('[useEvents] RSVP to event:', eventId, 'with data:', rsvpData);
      
      const response = await $fetch<{ success: boolean; data: any; message: string }>(`/api/events/${eventId}/rsvp`, {
        method: 'POST',
        body: {
          ...rsvpData,
          event_id: eventId,
          member_id: user.value?.id || ''
        }
      });

      if (response.success) {
        // Find event by event_id first, then fallback to database ID
        let eventIndex = events.value.findIndex(e => e.event_id === eventId);
        if (eventIndex === -1) {
          eventIndex = events.value.findIndex(e => (e as any).Id === eventId || e.id === eventId);
        }
        
        console.log('[useEvents] Event found at index:', eventIndex, 'using event_id:', eventId);
        
        if (eventIndex !== -1) {
          const event = events.value[eventIndex];
          
          // Update RSVP status
          event.user_rsvp = response.data;
          
          // Calculate attendee count including guests
          if (rsvpData.rsvp_status === 'confirmed') {
            const currentCount = parseInt(event.current_attendees || '0');
            const guestCount = parseInt(rsvpData.extra_guests || '0');
            const totalAdded = 1 + guestCount; // Member + guests
            
            event.current_attendees = (currentCount + totalAdded).toString();
            
            console.log('[useEvents] Updated attendee count:', {
              previous: currentCount,
              added: totalAdded,
              new: event.current_attendees,
              guests: guestCount
            });
          }
          
          // Trigger reactivity
          events.value[eventIndex] = { ...event };
        }

        // Clear cache for fresh data on next load
        cache.clear();
        
        // Force refresh events data to ensure accuracy
        await fetchEvents({ force: true });
        
        return response.data;
      } else {
        throw new Error(response.message || 'Failed to RSVP');
      }
    } catch (err: any) {
      error.value = err.message || 'Failed to RSVP to event';
      console.error('Error RSVPing to event:', err);
      throw err;
    } finally {
      loading.value = false;
    }
  };

  /**
   * Cancel RSVP to an event
   */
  const cancelRSVP = async (eventId: string) => {
    loading.value = true;
    error.value = null;

    try {
      // Find the event to get current RSVP info
      let event = events.value.find(e => e.event_id === eventId);
      if (!event) {
        event = events.value.find(e => (e as any).Id === eventId || e.id === eventId);
      }
      
      if (!event?.user_rsvp) {
        throw new Error('No RSVP found to cancel');
      }

      const response = await $fetch<{ success: boolean; data: any; message: string }>(`/api/events/${eventId}/rsvp`, {
        method: 'DELETE'
      });

      if (response.success) {
        const eventIndex = events.value.findIndex(e => e === event);
        
        if (eventIndex !== -1) {
          const currentCount = parseInt(events.value[eventIndex].current_attendees || '0');
          const guestCount = parseInt(events.value[eventIndex].user_rsvp?.extra_guests || '0');
          const totalRemoved = 1 + guestCount; // Member + guests
          
          // Update attendee count and remove RSVP
          events.value[eventIndex].current_attendees = Math.max(0, currentCount - totalRemoved).toString();
          events.value[eventIndex].user_rsvp = undefined;
          
          // Trigger reactivity
          events.value[eventIndex] = { ...events.value[eventIndex] };
        }

        // Clear cache and refresh
        cache.clear();
        await fetchEvents({ force: true });
        
        return response.data;
      } else {
        throw new Error(response.message || 'Failed to cancel RSVP');
      }
    } catch (err: any) {
      error.value = err.message || 'Failed to cancel RSVP';
      console.error('Error canceling RSVP:', err);
      throw err;
    } finally {
      loading.value = false;
    }
  };

  /**
   * Update attendance for an event (board/admin only)
   */
  const updateAttendance = async (eventId: string, memberId: string, attended: boolean) => {
    loading.value = true;
    error.value = null;

    try {
      const response = await $fetch<{ success: boolean; data?: any; message: string }>(`/api/events/${eventId}/attendees`, {
        method: 'PATCH',
        body: {
          event_id: eventId,
          member_id: memberId,
          attended
        }
      });

      if (response.success) {
        // Update local event data
        const eventIndex = events.value.findIndex(e => e.id === eventId);
        if (eventIndex !== -1 && events.value[eventIndex].attendee_list) {
          const attendeeIndex = events.value[eventIndex].attendee_list!.findIndex(
            a => a.member_id === memberId
          );
          if (attendeeIndex !== -1) {
            events.value[eventIndex].attendee_list![attendeeIndex].attended = attended ? 'true' : 'false';
          }
        }

        // Return data if available, otherwise return success status
        return response.data || { success: true, message: response.message };
      } else {
        throw new Error(response.message || 'Failed to update attendance');
      }
    } catch (err: any) {
      error.value = err.message || 'Failed to update attendance';
      console.error('Error updating attendance:', err);
      throw err;
    } finally {
      loading.value = false;
    }
  };

  /**
   * Get events for calendar display
   */
  const getCalendarEvents = async (start: string, end: string) => {
    try {
      const response = await $fetch<EventsResponse>('/api/events', {
        query: {
          start_date: start,
          end_date: end,
          user_role: userTier.value,
          calendar_format: 'true'
        }
      });

      if (response.success) {
        return response.data;
      }
      return [];
    } catch (err) {
      console.error('Error fetching calendar events:', err);
      return [];
    }
  };

  /**
   * Get upcoming events for banners/widgets
   */
  const getUpcomingEvents = (limit = 5): Event[] => {
    const now = new Date();
    return events.value
      .filter(event => new Date(event.start_datetime) >= now)
      .sort((a, b) => new Date(a.start_datetime).getTime() - new Date(b.start_datetime).getTime())
      .slice(0, limit);
  };

  /**
   * Find event by ID
   */
  const findEventById = (eventId: string): Event | undefined => {
    return events.value.find(event => event.id === eventId);
  };

  /**
   * Check if user has RSVP'd to an event
   */
  const hasUserRSVP = (eventId: string): boolean => {
    const event = findEventById(eventId);
    return !!event?.user_rsvp;
  };

  /**
   * Get user's RSVP status for an event
   */
  const getUserRSVPStatus = (eventId: string): string | null => {
    const event = findEventById(eventId);
    return event?.user_rsvp?.rsvp_status || null;
  };

  /**
   * Update the upcoming event reference
   */
  const updateUpcomingEvent = (eventList: Event[]) => {
    const upcoming = eventList
      .filter(event => new Date(event.start_datetime) >= new Date())
      .sort((a, b) => new Date(a.start_datetime).getTime() - new Date(b.start_datetime).getTime());
    
    upcomingEvent.value = upcoming.length > 0 ? upcoming[0] : null;
  };

  /**
   * Clear cache manually
   */
  const clearCache = () => {
    cache.clear();
  };

  /**
   * Delete an event (board/admin only)
   */
  const deleteEvent = async (eventId: string) => {
    loading.value = true;
    error.value = null;

    try {
      const response = await $fetch<{ success: boolean; message: string; deleted: any }>(`/api/events/${eventId}`, {
        method: 'DELETE'
      });

      if (response.success) {
        // Remove event from local state
        const eventIndex = events.value.findIndex(e => 
          e.event_id === eventId || 
          e.id === eventId || 
          (e as any).Id === eventId
        );
        
        if (eventIndex !== -1) {
          events.value.splice(eventIndex, 1);
        }

        // Clear cache and refresh
        clearCache();
        await fetchEvents({ force: true });
        
        return response;
      } else {
        throw new Error(response.message || 'Failed to delete event');
      }
    } catch (err: any) {
      error.value = err.message || 'Failed to delete event';
      console.error('Error deleting event:', err);
      throw err;
    } finally {
      loading.value = false;
    }
  };

  /**
   * Refresh events data
   */
  const refreshEvents = async () => {
    clearCache();
    return await fetchEvents({ force: true });
  };

  // Utility functions for date handling
  function startOfMonth(date: Date): Date {
    return new Date(date.getFullYear(), date.getMonth(), 1);
  }

  function endOfMonth(date: Date): Date {
    return new Date(date.getFullYear(), date.getMonth() + 1, 0);
  }

  function addMonths(date: Date, months: number): Date {
    const result = new Date(date);
    result.setMonth(result.getMonth() + months);
    return result;
  }

  return {
    // Reactive state
    events,
    loading,
    error,
    upcomingEvent,

    // Methods
    fetchEvents,
    createEvent,
    deleteEvent,
    rsvpToEvent,
    cancelRSVP,
    updateAttendance,
    getCalendarEvents,
    getUpcomingEvents,
    findEventById,
    hasUserRSVP,
    getUserRSVPStatus,
    clearCache,
    refreshEvents
  };
};
