import React, { useState, useEffect, useContext, useCallback } from "react";
import axios from "axios";
import { toast } from "react-toastify";

import { SSEContext } from "../context/SSEContext";
import { AuthContext } from "../context/AuthContext";

const Events = () => {
  const { auth } = useContext(AuthContext);
  const { connected, on, off, subscribe, unsubscribe } = useContext(SSEContext);
  const [events, setEvents] = useState([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);
  const [joinedEvents, setJoinedEvents] = useState(new Set());

  // Load events from API
  const loadEvents = useCallback(async () => {
    try {
      setLoading(true);
      const res = await axios.get("/api/events");
      setEvents(res.data);
      setError(null);
    } catch (err) {
      setError("Failed to load events. Please try again later.");
      console.error("Error loading events:", err);
    } finally {
      setLoading(false);
    }
  }, []);

  useEffect(() => {
    loadEvents();
  }, [loadEvents]);

  // Subscribe to global events topic on mount
  useEffect(() => {
    if (!connected) return;

    subscribe(["events"]);

    return () => {
      unsubscribe(["events"]);
    };
  }, [connected, subscribe, unsubscribe]);

  // Handle real-time event updates
  useEffect(() => {
    if (!connected) return;

    const handleEventUpdate = (data) => {
      console.log("Received event update:", data);

      if (data.type === "participants_updated") {
        // Update participant count for specific event
        setEvents((prevEvents) =>
          prevEvents.map((event) =>
            event._id === data.eventId
              ? { ...event, participants: data.participants }
              : event
          )
        );
      } else if (data.type === "new_event") {
        // Add new event to the list
        setEvents((prevEvents) => [data.event, ...prevEvents]);
      } else if (data.type === "event_updated") {
        // Update existing event
        setEvents((prevEvents) =>
          prevEvents.map((event) =>
            event._id === data.event._id ? data.event : event
          )
        );
      } else if (data.type === "event_deleted") {
        // Remove deleted event
        setEvents((prevEvents) =>
          prevEvents.filter((event) => event._id !== data.eventId)
        );
      }
    };

    // Subscribe to event updates
    on("eventUpdate", handleEventUpdate);

    // Cleanup on unmount
    return () => {
      off("eventUpdate", handleEventUpdate);
    };
  }, [connected, on, off]);

  // Subscribe to individual event topics when viewing events
  useEffect(() => {
    if (!connected) return;

    // Subscribe to each event topic for real-time updates
    const newEventIds = events
      .map((event) => event._id)
      .filter((id) => !joinedEvents.has(id));

    if (newEventIds.length > 0) {
      subscribe(newEventIds.map((id) => `event_${id}`));
      setJoinedEvents((prev) => new Set([...prev, ...newEventIds]));
    }

    // Cleanup: unsubscribe from event topics that are no longer in the list
    return () => {
      const eventIdsToUnsubscribe = Array.from(joinedEvents).filter(
        (id) => !events.some((event) => event._id === id)
      );
      if (eventIdsToUnsubscribe.length > 0) {
        unsubscribe(eventIdsToUnsubscribe.map((id) => `event_${id}`));
      }
    };
  }, [events, connected, subscribe, unsubscribe, joinedEvents]);

  const rsvp = async (id) => {
    if (!auth.isAuthenticated) {
      toast.warning("Please login to RSVP for events");
      return;
    }

    try {
      const token = localStorage.getItem("token");
      const res = await axios.put(
        `/api/events/rsvp/${id}`,
        {},
        {
          headers: {
            "x-auth-token": token,
          },
        }
      );

      setEvents(
        events.map((event) =>
          event._id === id ? { ...event, participants: res.data } : event
        )
      );
      toast.success("Successfully RSVP'd to event!");
    } catch (err) {
      console.error("Error RSVPing to event:", err);
      const errorMessage =
        err.response?.data?.msg ||
        err.response?.data?.message ||
        "Failed to RSVP. Please try again.";
      toast.error(errorMessage);
    }
  };

  if (loading) {
    return (
      <div className="text-center mt-5">
        <div className="spinner-border" role="status">
          <span className="sr-only">Loading...</span>
        </div>
        <p>Loading events...</p>
      </div>
    );
  }

  if (error) {
    return (
      <div className="alert alert-danger m-3" role="alert">
        {error}
        <button className="btn btn-primary ml-3" onClick={loadEvents}>
          Retry
        </button>
      </div>
    );
  }

  return (
    <div data-testid="events-container">
      <div className="d-flex justify-content-between align-items-center mb-3">
        <h1>Events</h1>
        {connected && (
          <span className="badge badge-success" data-testid="events-live-updates">
            <span className="mr-1">&#9679;</span> Live Updates
          </span>
        )}
      </div>

      {events.length === 0 ? (
        <div className="alert alert-info" data-testid="no-events-message">
          No events available at the moment. Check back later!
        </div>
      ) : (
        <div className="row" data-testid="events-list">
          {events.map((event) => {
            const eventDate = new Date(event.date);
            const isUpcoming = eventDate > new Date();

            return (
              <div key={event._id} className="col-md-6 mb-4" data-testid={`event-card-${event._id}`}>
                <div className="card h-100">
                  <div className="card-body">
                    <h5 className="card-title" data-testid={`event-title-${event._id}`}>{event.title}</h5>
                    <p className="card-text" data-testid={`event-description-${event._id}`}>{event.description}</p>

                    <div className="mb-2">
                      <small className="text-muted" data-testid={`event-date-${event._id}`}>
                        <strong>Date:</strong> {eventDate.toLocaleDateString()}{" "}
                        {eventDate.toLocaleTimeString()}
                      </small>
                    </div>

                    <div className="mb-2">
                      <small className="text-muted" data-testid={`event-location-${event._id}`}>
                        <strong>Location:</strong> {event.location}
                      </small>
                    </div>

                    {event.organizer && (
                      <div className="mb-2">
                        <small className="text-muted" data-testid={`event-organizer-${event._id}`}>
                          <strong>Organizer:</strong>{" "}
                          {event.organizer.name || event.organizer}
                        </small>
                      </div>
                    )}

                    <div className="mt-3">
                      <span
                        className={`badge badge-${
                          isUpcoming ? "success" : "secondary"
                        } mr-2`}
                        data-testid={`event-status-${event._id}`}
                      >
                        {isUpcoming ? "Upcoming" : "Past"}
                      </span>
                      <span className="badge badge-info" data-testid={`event-participants-${event._id}`}>
                        {event.participants?.length || 0} Participants
                      </span>
                    </div>

                    {isUpcoming && auth.isAuthenticated && (
                      <button
                        className="btn btn-primary btn-sm mt-3 btn-block"
                        onClick={() => rsvp(event._id)}
                        data-testid={`rsvp-btn-${event._id}`}
                      >
                        RSVP
                      </button>
                    )}
                  </div>
                </div>
              </div>
            );
          })}
        </div>
      )}
    </div>
  );
};

export default Events;
