import React, { useState, useEffect, useRef } from "react";
import { Agent, GenerationsByPk } from "../interfaces/AgentInterfaces";
import useCharacters from "../hooks/useCharacters";
import RandomAgentCard from "../components/RandomAgentCard"; // Import the new component
import LoadedAgentCard from "../components/LoadedAgentCard"; // Import the new component
import { inconsistentImageLambda } from "../api/leonardoApi";
import { createBlankAgent } from "../utils/agentUtils";
import { createAgent } from "../api/agentsAPI";
import { generateRandomAgent } from "../utils/generateRandomAgent";
import imageTraits from "../assets/generate-random-agents/imageTraits.json";
import characterConcepts from "../assets/generate-random-agents/characterConcepts.json";
import famousFigures from "../assets/generate-random-agents/famousFigures.json";
import LunaQuantumchef from "../assets/example-agents/Luna_Quantumchef_master.json";
import CosmicCurator from "../assets/example-agents/Cosmic_Curator_master.json";
import GavelGlitch from "../assets/example-agents/Gavel_Glitch_master.json";
import Sidebar from "../components/sidebar";
import { Search, Filter as FilterIcon } from "lucide-react";
import { motion } from "framer-motion";
import { useMemo } from "react";
import { useNavigate } from "react-router-dom";
import { useAgent } from '../context/AgentContext';

const LEONARDO_MODEL_ID = "e71a1c2f-4f80-4800-934f-2c68979d8cc8";
const LEONARDO_STYLE_UUID = "b2a54a51-230b-4d4f-ad4e-8409bf58645f";

// Helper function to get random trait
const getRandomTrait = (traitArray: string[]): string => {
  return traitArray[Math.floor(Math.random() * traitArray.length)];
};

// Add a utility function to handle image loading
const loadImageWithFallback = async (url: string): Promise<string> => {
  try {
    const response = await fetch(url, {
      mode: "cors",
      credentials: "omit", // Don't send cookies
      headers: {
        Accept: "image/*",
      },
    });

    if (!response.ok) {
      throw new Error("Image failed to load");
    }

    return url;
  } catch (error) {
    console.error("[AgentGallery] Error loading image:", error);
    return "Error loading image. Regenerate again";
  }
};

// Add this helper function near the top with other utility functions
const generateCharacterConcept = (): string => {
  const profession = getRandomTrait(characterConcepts.professions);
  const personality = getRandomTrait(characterConcepts.personalities);
  const origin = getRandomTrait(characterConcepts.origins);
  const power = getRandomTrait(characterConcepts.specialPowers);
  const goal = getRandomTrait(characterConcepts.goals);

  // Randomly choose between different concept formats
  const conceptFormats = [
    `A ${personality} ${profession} who ${power} and is ${origin}`,
    `${profession} ${origin}, who ${power} while ${goal}`,
    `A ${personality} individual ${origin} working as a ${profession}, with the ability to ${power}`,
    `An extraordinary ${profession} ${origin} on a mission of ${goal}`,
    `A remarkable ${personality} being who ${power}, working as a ${profession} while ${goal}`,
    `Create a name and try to incorporate the ${profession} into the name. For example,
    if the profession was a Dr. then the name could be Dr.{Name} `,
  ];
  const conceptFormat2 = [
    `Create a parody meme of ${getRandomFamousPerson()}. The meme should be a funny and clever meme that captures the essence of the person and their achievements. Make it witty and memorable while staying respectful. Include their most iconic features, expressions, or famous quotes if applicable.
    Make sure to use their name as part of their agent name. It is best to make a variation of their name. For example, if the person is Elon Musk, then the agent name could be Elon Musk Jr., Elon Gate, Trump Bot, Trump Tron, etc. Make something unique and memorable that could go viral within the first 24 hours of being posted.`,
  ];

  // 80% chance of conceptFormat1, 20% chance of conceptFormat2
  return Math.random() < 0.35
    ? getRandomTrait(conceptFormats)
    : getRandomTrait(conceptFormat2);
};

// Add this helper function near other utility functions
const getRandomFamousPerson = (): string => {
  const categories = Object.keys(famousFigures);
  const randomCategory =
    categories[Math.floor(Math.random() * categories.length)];
  const figures = famousFigures[randomCategory as keyof typeof famousFigures];
  return figures[Math.floor(Math.random() * figures.length)];
};

// Add this function to convert master JSON to Agent type
const convertMasterJsonToAgent = (masterJson: any): Agent => {
  return {
    id: Math.floor(Math.random() * 1000000).toString(),
    name: masterJson.agent.agent_details.name || "",
    avatar: masterJson.agent.profile_image?.details?.url || "",
    shortDescription: masterJson.agent.agent_details.backstory || "",
    tags: masterJson.agent.agent_details.hashtags || [],
    personality: masterJson.agent.agent_details.personality || [],
    communicationStyle:
      masterJson.agent.agent_details.communication_style || [],
    emojis: masterJson.agent.agent_details.emojis || [],
    universe: masterJson.agent.agent_details.universe || "",
    backstory: masterJson.agent.agent_details.backstory || "",
    topic_expertise: masterJson.agent.agent_details.topic_expertise || [],
    isExample: true, // Add this flag to identify example agents
  };
};

const AgentGallery: React.FC = () => {
  // Add selected agent state
  // const [selectedAgent, setSelectedAgent] = useState<Agent | null>(null);
  const { characters: loadedAgents } = useCharacters();
  const [randomAgents, setRandomAgents] = useState<Agent[]>([]);
  const [filter, setFilter] = useState("all");
  const [searchQuery, setSearchQuery] = useState("");
  const [showFilters, setShowFilters] = useState(false);
  const initialMount = useRef(true);
  const navigate = useNavigate()

  // Inside AgentGallery component:
  const { setSelectedAgent } = useAgent();

  // Define generateRandomAgentData inside AgentGallery so it's accessible to child components
  const generateRandomAgentData = async (): Promise<Agent> => {
    try {
      const concept = generateCharacterConcept();

      const newRandomAgentData = await generateRandomAgent(concept);
      const agentObject = newRandomAgentData.agent;
      const agentDetails = agentObject.agent_details;

      return {
        id: Math.floor(Math.random() * 1000000).toString(),
        name: agentDetails.name.replace("_", " ") || "",
        avatar: "",
        shortDescription: "...",
        tags: agentDetails.hashtags || [],
        personality: agentDetails.personality || [],
        communicationStyle: agentDetails.communication_style || [],
        emojis: agentDetails.emojis || [],
        universe: agentDetails.universe || "",
        backstory: agentDetails.backstory || "",
        concept: concept,
        topic_expertise: agentDetails.topic_expertise || [],
      };
    } catch (error) {
      console.error("[generateRandomAgentData] Error:", error);
      throw error;
    }
  };

  const filterAgentsByName = (
    agents: any[],
    isLoadedAgent: boolean = false
  ): any[] => {
    if (!searchQuery) return agents;

    const lowerQuery = searchQuery.toLowerCase().trim();

    return agents.filter((agent) => {
      if (isLoadedAgent) {
        // Handle loaded agents structure where properties are in agent.agent.agent_details
        const details = agent?.agent?.agent_details;
        if (!details) return false;

        return (
          details.name?.toLowerCase().includes(lowerQuery) ||
          details.backstory?.toLowerCase().includes(lowerQuery) ||
          details.universe?.toLowerCase().includes(lowerQuery) ||
          details.hashtags?.some((tag: string) =>
            tag.toLowerCase().includes(lowerQuery)
          ) ||
          details.personality?.some((trait: string) =>
            trait.toLowerCase().includes(lowerQuery)
          ) ||
          details.topic_expertise?.some((topic: string) =>
            topic.toLowerCase().includes(lowerQuery)
          ) ||
          details.communication_style?.some((style: string) =>
            style.toLowerCase().includes(lowerQuery)
          )
        );
      } else {
        // Handle random agents structure (keeping existing logic)
        return (
          agent.name?.toLowerCase().includes(lowerQuery) ||
          agent.shortDescription?.toLowerCase().includes(lowerQuery) ||
          agent.backstory?.toLowerCase().includes(lowerQuery) ||
          agent.tags?.some((tag) => tag.toLowerCase().includes(lowerQuery)) ||
          agent.personality?.some((trait) =>
            trait.toLowerCase().includes(lowerQuery)
          ) ||
          agent.topic_expertise?.some((topic) =>
            topic.toLowerCase().includes(lowerQuery)
          )
        );
      }
    });
  };

  const filteredRandomAgents = filterAgentsByName(randomAgents);
  const filteredLoadedAgents = filterAgentsByName(loadedAgents, true);

  useEffect(() => {
    if (initialMount.current) {
      initialMount.current = false;
      const exampleAgents = [
        convertMasterJsonToAgent(LunaQuantumchef),
        convertMasterJsonToAgent(CosmicCurator),
        convertMasterJsonToAgent(GavelGlitch),
      ];
      setRandomAgents(exampleAgents);
    }
  }, []);

  const handleAddAgent = async (agent: Agent, leonardoResponse: any) => {
    try {
      // Create a new blank agent with proper initialization
      const newAgent = createBlankAgent();

      if (!newAgent.agent) {
        console.error(
          "[handleAddAgent] - New agent object is not properly initialized"
        );
        return;
      }

      // Ensure agent.agent_details exists before accessing
      if (!newAgent.agent.agent_details) {
        console.error(
          "[handleAddAgent] - Agent details are not properly initialized"
        );
        return;
      }

      // Log the concept being saved

      // populate our concept
      newAgent.agent.concept = agent.concept || "";

      // populate our agent details
      const agentDetails = newAgent.agent.agent_details;
      agentDetails.name = agent?.name || "";
      agentDetails.personality = agent?.personality || [];
      agentDetails.communication_style = agent?.communicationStyle || [];
      agentDetails.emojis = agent?.emojis || [];
      agentDetails.hashtags = agent?.hashtags || [];
      agentDetails.universe = agent?.universe || "";
      agentDetails.topic_expertise = agent?.topic_expertise || [];
      agentDetails.backstory = agent?.backstory || "";

      // Ensure profile_image_options array exists and has at least one element
      if (!newAgent.agent.profile_image_options) {
        newAgent.agent.profile_image_options = [];
      }
      if (newAgent.agent.profile_image_options.length === 0) {
        newAgent.agent.profile_image_options.push({
          generations_by_pk: {} as GenerationsByPk,
        });
      }

      // Ensure profile_image exists and has details
      if (!newAgent.agent.profile_image) {
        newAgent.agent.profile_image = {
          details: {
            url: "",
            image_id: "",
            generationId: "",
          },
        };
      }

      // Populate the image data
      if (leonardoResponse?.generations_by_pk) {
        const generation_by_pk = leonardoResponse.generations_by_pk;
        newAgent.agent.profile_image_options[0].generations_by_pk =
          generation_by_pk;

        if (generation_by_pk.generated_images?.[0]) {
          const imageDetails = newAgent.agent.profile_image.details;
          imageDetails.url = generation_by_pk.generated_images[0].url;
          imageDetails.image_id = generation_by_pk.generated_images[0].id;
          imageDetails.generationId = generation_by_pk.id;
        }
      }

      // Call our api to save the new agent
      const newAgentResponse = await createAgent(newAgent);

      return newAgentResponse;
    } catch (error) {
      console.error("[handleAddAgent] Error:", error);
      throw error;
    }
  };

  // Update the handleSingleAgentRegeneration function
  const handleSingleAgentRegeneration = async (
    agentId: string
  ): Promise<void> => {
    try {
      // Show loading state immediately with loading name
      setRandomAgents((prevAgents) =>
        prevAgents.map((agent) =>
          agent.id === agentId
            ? {
              ...agent,
              name: "Generating Agent...", // Add loading name
              isLoading: true,
              personality: [],
              communicationStyle: [],
              emojis: [],
              hashtags: [],
            }
            : agent
        )
      );

      const currentAgent = randomAgents.find((agent) => agent.id === agentId);
      if (!currentAgent) return;

      // Generate new agent data
      const newAgentData = await generateRandomAgentData();

      const newAgent = {
        ...newAgentData,
        id: currentAgent.id,
      };

      // Update UI to show we're now generating the image
      setRandomAgents((prevAgents) =>
        prevAgents.map((agent) =>
          agent.id === agentId
            ? {
              ...newAgent,
              isLoading: true,
            }
            : agent
        )
      );

      // Incorporate the concept into the prompt
      const prompt = `Generate an anime character portrait of ${newAgent.name
        } with ${getRandomTrait(imageTraits.hairStyles)} ${getRandomTrait(
          imageTraits.hairColors
        )} hair, ${getRandomTrait(
          imageTraits.eyeColors
        )} eyes, wearing ${getRandomTrait(
          imageTraits.clothingStyles
        )} style clothing. Their personality can be described as ${newAgent.personality?.join(", ") || "unknown"
        }. Scene: ${getRandomTrait(
          imageTraits.backgrounds
        )}. Style: high quality, detailed anime art, character portrait. Concept: ${newAgent.concept
        } `;

      const payload = {
        prompt: prompt,
        modelId: LEONARDO_MODEL_ID,
        styleUUID: LEONARDO_STYLE_UUID,
        num_images: 4,
      };
      const imageResponse = await inconsistentImageLambda(payload);

      if (!imageResponse?.generations_by_pk?.generated_images?.[0]?.url) {
        throw new Error("No image URL received");
      }

      const imageUrl = imageResponse.generations_by_pk.generated_images[0].url;
      const loadedImageUrl = await loadImageWithFallback(imageUrl);

      // Update with all necessary data for saving
      setRandomAgents((prevAgents) =>
        prevAgents.map((agent) =>
          agent.id === agentId
            ? {
              ...newAgent,
              avatar: loadedImageUrl,
              isLoading: false,
              leonardoResponse: imageResponse, // Add the full Leonardo response
              leonardoImage:
                imageResponse.generations_by_pk.generated_images[0], // Add the image data
            }
            : agent
        )
      );
    } catch (error) {
      console.error("[AgentGallery] Error regenerating single agent:", error);
      setRandomAgents((prevAgents) =>
        prevAgents.map((agent) =>
          agent.id === agentId
            ? {
              ...agent,
              isLoading: false,
            }
            : agent
        )
      );
    }
  };



  // Update handleSelectAgent:
  const handleSelectAgent = async (agent: Agent) => {
    setSelectedAgent(agent);
    navigate('/chat');
  };
  // // Add handleSelectAgent function
  // const handleSelectAgent = async (agent: Agent) => {
  //   console.log("[handleSelectAgent] Selecting agent:", agent);
  //   try {
  //     // Add a small delay to show the loading state
  //     navigate("/chat")
  //   } catch (error) {
  //     console.error("[handleSelectAgent] Error:", error);
  //     throw error;
  //   }
  // };

  useEffect(() => {
    if (initialMount.current) {
      initialMount.current = false;
      // Load example agents instead of generating new ones
      const exampleAgents = [
        convertMasterJsonToAgent(LunaQuantumchef),
        convertMasterJsonToAgent(CosmicCurator),
        convertMasterJsonToAgent(GavelGlitch),
      ];
      setRandomAgents(exampleAgents);
    }
  }, []);

  return (
    <div className="flex">
      <Sidebar />
      <div className="h-screen w-full overflow-y-scroll bg-gray-50 p-10">
        <div className="p-5 mb-[4rem] rounded-xl shadow-xl flex items-center justify-between">
          <div className="text-3xl font-semibold text-gray-600 font-orbitron">
            Browse Agents
          </div>
          <div className="flex items-center space-x-3 justify-end"></div>
        </div>
        <div className="max-w-7xl mx-auto">
          {/* Search and Filter Header */}
          <div className="mb-8 space-y-4">
            <div className="flex gap-4 items-center">
              <div className="relative flex-1">
                <Search
                  className="absolute left-3 top-1/2 -translate-y-1/2 text-gray-400"
                  size={20}
                />
                <input
                  type="text"
                  placeholder="Search agents by name, description, or tags..."
                  className="w-full pl-10 pr-4 py-3 placeholder:text-neutral-600 bg-neutral-200 shadow-inner text-neutral-600 rounded-lg outline-none focus:ring-2 focus:ring-yellow-400 focus:border-transparent"
                  value={searchQuery}
                  onChange={(e) => setSearchQuery(e.target.value)}
                />
              </div>
              <button
                onClick={() => setShowFilters(!showFilters)}
                className="flex items-center gap-2 px-4 py-3 bg-gradient-to-r from-yellow-400 to-yellow-500 hover:from-yellow-500 hover:to-yellow-600 text-gray-900 rounded-lg font-medium transition-all"
              >
                <FilterIcon size={20} />
                Filters
              </button>
            </div>

            {/* Filter Pills */}
            <div className="flex flex-wrap gap-3">
              {["all", "random", "yourAgents"].map((filterOption) => (
                <button
                  key={filterOption}
                  className={`px-4 py-2 rounded-full font-medium transition-all ${filter === filterOption
                      ? "bg-gradient-to-r from-yellow-400 to-yellow-500 text-gray-900"
                      : "bg-neutral-200 text-neutral-600 hover:bg-neutral-400"
                    }`}
                  onClick={() => setFilter(filterOption)}
                >
                  {filterOption === "all"
                    ? "All"
                    : filterOption === "random"
                      ? "Random"
                      : "Your Agents"}
                </button>
              ))}
            </div>
          </div>

          {/* Display message when no results are found */}
          {searchQuery &&
            !filteredRandomAgents.length &&
            !filteredLoadedAgents.length && (
              <div className="text-center py-8 text-gray-500">
                No agents found matching "{searchQuery}"
              </div>
            )}

          <div>
            {(filter === "all" || filter === "yourAgents") &&
              filteredLoadedAgents.length > 0 && (
                <>
                  <h2 className="text-xl font-semibold mt-8 mb-4 text-gray-700">
                    Agents Gallery
                  </h2>
                  <div className="flex gap-6 pb-4 flex-wrap">
                    {/* Horizontal scrolling container */}
                    {filteredLoadedAgents.map((agent) => {
                      const randomWidth =
                        Math.floor(Math.random() * (500 - 200 + 1)) + 200;
                      return (
                        <div
                          key={
                            agent?.agent?.agent_details?.name ||
                            Math.random().toString()
                          }
                          style={{ width: `${randomWidth}px` }}
                          className="flex-grow"
                        >
                          <LoadedAgentCard
                            agent={agent}
                            onSelect={handleSelectAgent}
                          />
                        </div>
                      );
                    })}
                  </div>
                </>
              )}
          </div>
        </div>
      </div>
    </div>
  );
};

export default AgentGallery;
