import { Link, Outlet, useLoaderData, useParams, useOutletContext, useLocation } from "@remix-run/react";
import { useState, useEffect } from "react";
import { useSocket } from "../context";
import { L33tADSPLC, L33tADSPLCImpl } from "l33t-lib";
import { loaderPLCs } from "../loaders";

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

export const loader = loaderPLCs;

export default function PLCs() {
  const socket = useSocket();
  const { id } = useParams<{ id: string }>();
  const [plcs, setPlcs] = useState<Record<string, L33tADSPLC>>(useLoaderData<typeof loader>());
  const location = useLocation();
  const showDetail = location.pathname.split('/').length > 2;

  const { toggleSelection, selectedIds } = useOutletContext<ContextType>();

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

      const newId = `plc_${Date.now()}`;

      // Create new PLC instance
      const newPLC = new L33tADSPLCImpl();
      // Set default values
      newPLC.description = "New PLC";
      newPLC.ip = "";
      newPLC.driver = "";
      newPLC.connected = false;
      newPLC.boundVariables = [];
      newPLC.values = {};
      newPLC.timedLast = Date.now();
      newPLC.timedPrevious = Date.now();
      newPLC.timedTTL = 200;

      socket.emit("l33t_add_plc", newId, newPLC);
    } catch (error) {
      console.error("Error adding PLC:", error);
    }
  };

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

    const handlePLCUpdate = (plcId: string, updatedPLC: L33tADSPLC | null) => {
      if (updatedPLC === null) {
        setPlcs(prevPlcs => {
          const newPlcs = { ...prevPlcs };
          delete newPlcs[plcId];
          return newPlcs;
        });
      } else {
        setPlcs(prevPlcs => ({
          ...prevPlcs,
          [plcId]: updatedPLC
        }));
      }
    };

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

    socket.on("l33t_plc_update", handlePLCUpdate);
    socket.on("l33t_delete_plc_result", handleDeleteResult);

    return () => {
      socket.off("l33t_plc_update", handlePLCUpdate);
      socket.off("l33t_delete_plc_result", handleDeleteResult);
    };
  }, [socket]);

  return (
    <div className={`container mx-auto pt-10 ${showDetail ? 'pr-1/3' : ''}`}>
      <div className="flex items-center gap-4 mb-4">
        <h1 className="text-3xl text-white">PLCs</h1>
        <button
          onClick={addPLC}
          className="text-white"
          aria-label="Add PLC"
        >
          <i className="fa-plus fa-solid"></i>
        </button>
      </div>

      <div className="grid grid-cols-3 md:grid-cols-3 lg:grid-cols-4 gap-4">
        {Object.entries(plcs).map(([plcId, plcData]) => {
          if (!plcData) return null;
          
          return (
            <Link
              to={`${plcId}`}
              key={plcId}
              className="flex flex-col relative p-4 rounded shadow-lg bg-black/50 text-white hover:bg-black/60 transition-colors"
            >
              <div className="flex items-center gap-2 mb-2">
                <button 
                  onClick={(e) => {
                    e.preventDefault();
                    e.stopPropagation();
                    toggleSelection(plcId);
                  }}
                  className="absolute top-4 right-4"
                >
                  <i className={`fa-solid ${selectedIds.includes(plcId) ? 'fa-check-square text-blue-400' : 'fa-square text-gray-400'}`}></i>
                </button>
                <h1 className="text-lg font-semibold">{plcId}</h1>
                <div className={`w-2.5 h-2.5 rounded-full ${plcData.connected ? 'bg-green-500' : 'bg-red-500'}`}></div>
              </div>
              <div className="flex items-center gap-2">
                {plcData.connected ? "Connected" : "Disconnected"}
              </div>
              <div className="mb-6">
                <small>
                  Exporting {Object.keys(plcData?.boundVariables || {}).length} variables
                </small>
              </div>
            </Link>
          );
        })}
      </div>
      <Outlet />
    </div>
  );
}