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

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

/**
 * TaskList component displays maintenance tasks and allows task completion
 * Includes real-time updates via SSE
 */
const TaskList = () => {
  const { auth } = useContext(AuthContext);
  const { connected, on, off, subscribe, unsubscribe } = useContext(SSEContext);
  const [tasks, setTasks] = useState([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);
  const [completingTaskId, setCompletingTaskId] = useState(null);

  // Load tasks from API
  const loadTasks = useCallback(async () => {
    try {
      setLoading(true);
      setError(null);
      const res = await axios.get("/api/tasks");
      setTasks(res.data);
    } catch (err) {
      console.error("Error loading tasks:", err);
      const errorMessage =
        err.response?.data?.msg ||
        err.response?.data?.message ||
        "Failed to load tasks. Please try again later.";
      setError(errorMessage);
      toast.error(errorMessage);
    } finally {
      setLoading(false);
    }
  }, []);

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

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

    subscribe(["tasks"]);

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

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

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

      if (data.type === "task_completed") {
        // Update specific task status
        setTasks((prevTasks) =>
          prevTasks.map((task) =>
            task._id === data.taskId ? { ...task, status: "completed" } : task
          )
        );
        toast.success("Task completed!");
      } else if (data.type === "new_task") {
        // Add new task to the list
        setTasks((prevTasks) => [data.task, ...prevTasks]);
        toast.info("New task available!");
      } else if (data.type === "task_updated") {
        // Update existing task
        setTasks((prevTasks) =>
          prevTasks.map((task) =>
            task._id === data.task._id ? data.task : task
          )
        );
      } else if (data.type === "task_deleted") {
        // Remove deleted task
        setTasks((prevTasks) =>
          prevTasks.filter((task) => task._id !== data.taskId)
        );
      }
    };

    // Subscribe to task updates
    on("taskUpdate", handleTaskUpdate);

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

  // Complete a task
  const completeTask = async (id) => {
    if (!auth.isAuthenticated) {
      toast.warning("Please login to complete tasks");
      return;
    }

    try {
      setCompletingTaskId(id);
      const token = localStorage.getItem("token");
      const res = await axios.put(
        `/api/tasks/${id}`,
        {},
        {
          headers: {
            "x-auth-token": token,
          },
        }
      );
      setTasks(tasks.map((task) => (task._id === id ? res.data : task)));
      toast.success("Task completed successfully!");
    } catch (err) {
      console.error("Error completing task:", err);
      const errorMessage =
        err.response?.data?.msg ||
        err.response?.data?.message ||
        "Failed to complete task. Please try again.";
      toast.error(errorMessage);
    } finally {
      setCompletingTaskId(null);
    }
  };

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

  if (error) {
    return (
      <div className="alert alert-danger m-3" role="alert">
        <h4 className="alert-heading">Error Loading Tasks</h4>
        <p>{error}</p>
        <hr />
        <button className="btn btn-primary" onClick={loadTasks}>
          Retry
        </button>
      </div>
    );
  }

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

      {tasks.length === 0 ? (
        <div className="alert alert-info" data-testid="no-tasks-message">
          No tasks available at the moment. Check back later!
        </div>
      ) : (
        <ul className="list-group" data-testid="tasks-list">
          {tasks.map((task) => (
            <li
              key={task._id}
              className="list-group-item d-flex justify-content-between align-items-center"
              data-testid={`task-item-${task._id}`}
            >
              <div>
                <strong>{task.description}</strong>
                <br />
                <span
                  className={`badge badge-${
                    task.status === "pending" ? "warning" : "success"
                  } mr-2`}
                  data-testid={`task-status-${task._id}`}
                >
                  {task.status}
                </span>
                {task.street && (
                  <small className="text-muted">Street: {task.street.name || task.street}</small>
                )}
                {task.assignedTo && (
                  <small className="text-muted ml-2">
                    Assigned to: {task.assignedTo.name || task.assignedTo}
                  </small>
                )}
              </div>
              {task.status === "pending" && auth.isAuthenticated && (
                <button
                  className="btn btn-sm btn-success"
                  onClick={() => completeTask(task._id)}
                  disabled={completingTaskId === task._id}
                  data-testid={`complete-task-btn-${task._id}`}
                >
                  {completingTaskId === task._id ? (
                    <>
                      <span
                        className="spinner-border spinner-border-sm mr-1"
                        role="status"
                        aria-hidden="true"
                      ></span>
                      Completing...
                    </>
                  ) : (
                    "Complete"
                  )}
                </button>
              )}
            </li>
          ))}
        </ul>
      )}
    </div>
  );
};

export default TaskList;
