import { Link, Outlet, useLoaderData, useOutletContext } from "@remix-run/react";
import { useState, useEffect } from "react";
import { useSocket } from "../context";
import { L33tAgent, L33tConfig, L33tMessage } from "l33t-lib";
import TimedStatus from "../components/TimedStatus";
import { loaderAgents } from "../loaders";

type ContextType = {
  toggleSelection: (id: string) => void;
  selectedIds: string[];
  memoryDB: any;
};

export const loader = loaderAgents;

export default function Stream() {
  const [agents, setAgents] = useState<Record<string, L33tAgent>>(useLoaderData<typeof loader>());
  const socket = useSocket();
  const { toggleSelection, selectedIds } = useOutletContext<ContextType>();

  useEffect(() => {
    if (!socket) return;

    const handleL33tUpdate = (id: string, updatedAgent: L33tAgent | null) => {
      console.log("UPDATE ag", updatedAgent);
      
      if (updatedAgent === null) {
        setAgents(prevAgents => {
          const newAgents = { ...prevAgents };
          delete newAgents[id];
          return newAgents;
        });
      } else {
        setAgents(prevAgents => ({
          ...prevAgents,
          [id]: updatedAgent
        }));
      }
    };

    const handleDeleteResult = (result: { success: boolean, error?: string }) => {
      console.log("Delete result received:", result);
      if (!result.success) {
        console.error("Failed to delete agent:", result.error);
      }
    };

    socket.on("l33t_agent_update", handleL33tUpdate);
    socket.on("l33t_delete_agent_result", handleDeleteResult);

    return () => {
      socket.off("l33t_agent_update", handleL33tUpdate);
      socket.off("l33t_delete_agent_result", handleDeleteResult);
    };
  }, [socket]);

  const addStream = async () => {
    try {
      if (!socket) {
        console.error("Socket connection not available");
        return;
      }

      const newId = `stream_${Date.now()}`;
      
      const emptyMessage = new L33tMessage(
        0, 
        "", 
        Date.now(),
        0, 
        []
      );
      
      const newAgent = new L33tAgent(
        emptyMessage,
        new L33tConfig(),
        []
      );

      newAgent.timedLast = Date.now();
      newAgent.timedPrevious = Date.now();
      newAgent.timedTTL = 200;

      socket.emit("l33t_add_agent", newId, newAgent);

      socket.once("l33t_add_agent_result", (result: { success: boolean, streamId?: string, error?: string }) => {
        console.log("result", result);
        if (result.success && result.streamId) {
          console.log("Stream added successfully:", result.streamId);
        } else {
          console.error("Failed to add stream:", result.error);
        }
      });

    } catch (error) {
      console.error("Error adding stream:", error);
    }
  };

  return (
    <div className="container mx-auto pt-10 text-white">
      <div className="flex items-center gap-4 mb-4">
        <h1 className="text-3xl">Streams</h1>
        <button
          onClick={addStream}
          className="text-white"
          aria-label="Add Stream"
        >
          <i className="fa-plus fa-solid"></i>
        </button>
      </div>

      {agents ? (
        <div className="grid grid-cols-3 md:grid-cols-3 lg:grid-cols-4 gap-4">

          {/* filter(Boolean) removes any null entries if PLC data was missing */}
          {Object.entries(agents).map(([id, agent]) => {
            if (!agent) return null;
            
            return (
              <Link
                key={id}
                to={`${id}/detections`}
                className="p-4 bg-black bg-opacity-50 rounded relative"
              >
                <div className="flex items-center justify-between mb-2">
                  <h1 className="text-lg font-semibold">{id}</h1>
                  <button 
                    onClick={(e) => {
                      e.preventDefault();
                      e.stopPropagation();
                      toggleSelection(id);
                    }}
                    className="z-20"
                  >
                    <i className={`fa-solid ${selectedIds.includes(id) ? 'fa-check-square text-blue-400' : 'fa-square text-gray-400'}`}></i>
                  </button>
                </div>

                <img
                  src={agent.lastMessage?.image}
                  alt={`Latest detection result for ID ${id}`}
                  className="w-full h-auto mb-2 rounded"
                />
                
                <TimedStatus timed={agent} />
              </Link>
            );
          }).filter(Boolean)}
        </div>
      ) : (
        <p>Ain't no stream at the moment 😢</p>
      )}

      <Outlet />
    </div>
  );
}