import { Avatar } from "@/components/ui/avatar";
import { ScrollArea } from "@/components/ui/scroll-area";
import { Button } from "@/components/ui/button";
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "@/components/ui/dropdown-menu";
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/components/ui/tooltip";
import { Message as MessageType, ResearchTree } from "@/lib/types";
import { Bot, Copy, MoreHorizontal, User2, ExternalLink, Loader2, SearchIcon, Terminal, ChevronDown, ChevronRight } from "lucide-react";
import React, { useState, useEffect, useMemo, useRef } from "react";
import ReactMarkdown from "react-markdown";
import remarkGfm from "remark-gfm";
import { Prism as SyntaxHighlighter } from "react-syntax-highlighter";
import { oneDark } from "react-syntax-highlighter/dist/cjs/styles/prism";
import { Badge } from "@/components/ui/badge";
import { Card, CardContent, CardHeader } from "@/components/ui/card";

// Component to display tool calls nicely
const ToolCallDisplay = ({ toolCall }: { toolCall: any }) => {
  const getDisplayArgs = () => {
    if (!toolCall.args) return "";
    if (typeof toolCall.args === "string") return toolCall.args;
    if (toolCall.args.query) return toolCall.args.query;
    if (toolCall.args.url) return toolCall.args.url;
    return JSON.stringify(toolCall.args);
  };

  const args = getDisplayArgs();

  return (
    <div className="my-1.5 border rounded-md bg-background/50 overflow-hidden group hover:bg-muted/30 transition-colors cursor-pointer">
      <div className="flex items-start px-3 py-2 gap-2 text-xs font-mono text-muted-foreground">
        <Terminal className="h-3 w-3 mt-0.5 flex-shrink-0" />
        <span className="font-semibold flex-shrink-0">{toolCall.name}</span>
        <span className="flex-1 truncate group-hover:whitespace-pre-wrap group-hover:break-words transition-all">
          {args}
        </span>
      </div>
    </div>
  );
};

// Function to extract all source URLs from the research tree
const extractAllSources = (tree: ResearchTree | undefined): Array<{ text: string; url: string }> => {
  if (!tree) return [];

  // Start with an empty set to avoid duplicates
  const uniqueSources = new Set<string>();

  // Recursive function to gather all sources
  const collectSources = (node: ResearchTree) => {
    // Add all sources from the current node
    if (node.sources && Array.isArray(node.sources)) {
      node.sources.forEach((url) => uniqueSources.add(url));
    }

    // Process all children recursively
    if (node.children && Array.isArray(node.children)) {
      node.children.forEach((child) => collectSources(child));
    }
  };

  // Start the collection process
  collectSources(tree);

  // Convert the set to an array of objects with text and url properties
  return Array.from(uniqueSources).map((url) => {
    // Try to extract a readable title from the URL
    let text = "";
    try {
      const urlObj = new URL(url);
      // Remove 'www.' if present and take the hostname
      text = urlObj.hostname.replace(/^www\./, "");

      // Add the pathname if it's not just "/"
      if (urlObj.pathname && urlObj.pathname !== "/") {
        // Format the pathname - keep it short and clean
        const path = urlObj.pathname.split("/").filter(Boolean);
        if (path.length > 0) {
          const lastPathSegment = path[path.length - 1]
            .replace(/[-_]/g, " ") // Replace dashes and underscores with spaces
            .replace(/\.html$|\.pdf$|\.php$/, ""); // Remove common extensions

          text = `${text} - ${lastPathSegment}`;
        }
      }
    } catch (e) {
      // If URL parsing fails, use the URL as is
      text = url;
    }

    return { text, url };
  });
};

// SourceLinks component for displaying research sources in a scrollable container
const SourceLinks = ({ links }: { links: Array<{ text: string; url: string }> }) => {
  if (!links || links.length === 0) return null;

  return (
    <div className="mt-4 mb-4">
      <h3 className="text-md font-semibold mb-2">Research Sources:</h3>
      <ScrollArea className="w-full h-[300px] overflow-auto border border-slate-200 dark:border-slate-700 rounded-xl shadow-sm p-1" type="always">
        <div className="space-y-2">
          {links.map((link, index) => {
            // Extract domain for display
            let domain = "";
            try {
              const urlObj = new URL(link.url);
              domain = urlObj.hostname.replace(/^www\./, "");
            } catch (e) {
              domain = "Unknown source";
            }

            return (
              <div key={index} className="flex items-start gap-2 group hover:bg-muted/50 p-2 rounded-md transition-colors">
                <ExternalLink className="h-4 w-4 text-muted-foreground flex-shrink-0 mt-1" />
                <div className="flex-1">
                  <a href={link.url} className="text-primary hover:underline text-sm block" target="_blank" rel="noopener noreferrer">
                    {domain}
                  </a>
                  <a href={link.url} className="text-xs text-muted-foreground hover:underline block truncate" target="_blank" rel="noopener noreferrer" title={link.url}>
                    {link.url}
                  </a>
                </div>
                <div className="opacity-0 group-hover:opacity-100 transition-opacity">
                  <TooltipProvider>
                    <Tooltip>
                      <TooltipTrigger asChild>
                        <Button
                          size="sm"
                          variant="ghost"
                          className="h-6 w-6 p-0"
                          onClick={(e) => {
                            e.preventDefault();
                            navigator.clipboard.writeText(link.url);
                          }}>
                          <Copy className="h-3 w-3" />
                        </Button>
                      </TooltipTrigger>
                      <TooltipContent>Copy link</TooltipContent>
                    </Tooltip>
                  </TooltipProvider>
                </div>
              </div>
            );
          })}
        </div>
      </ScrollArea>
    </div>
  );
};

// ImageGallery component for handling images in a scrollable container
const ImageGallery = ({ imageUrls }: { imageUrls: string[] }) => {
  const [loadedImages, setLoadedImages] = useState<string[]>([]);

  // Lazy load images using Intersection Observer
  useEffect(() => {
    const observer = new IntersectionObserver(
      (entries) => {
        entries.forEach((entry) => {
          if (entry.isIntersecting) {
            const img = entry.target as HTMLImageElement;
            const src = img.getAttribute("data-src");
            if (src) {
              img.src = src;
              observer.unobserve(img);
              setLoadedImages((prev) => [...prev, src]);
            }
          }
        });
      },
      { rootMargin: "100px" }
    );

    const imgPlaceholders = document.querySelectorAll(".lazy-image");
    imgPlaceholders.forEach((img) => observer.observe(img));

    return () => observer.disconnect();
  }, [imageUrls]);

  if (!imageUrls || imageUrls.length === 0) return null;

  return (
    <div className="mt-4 mb-4">
      <h3 className="text-md font-semibold mb-2">Relevant Images:</h3>
      <ScrollArea className="w-full h-[300px] overflow-auto border border-slate-200 dark:border-slate-700 rounded-xl shadow-sm p-1" type="always">
        <div className="p-2 grid grid-cols-2 md:grid-cols-4 gap-2">
          {imageUrls.map((url, index) => (
            <div key={index} className="image-container h-[150px]">
              <img
                className="lazy-image rounded-md w-full h-full object-cover shadow-sm border border-slate-100 dark:border-slate-800"
                src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='100' height='100' viewBox='0 0 100 100'%3E%3Crect width='100' height='100' fill='%23f1f1f1'/%3E%3C/svg%3E"
                data-src={url}
                alt={`Research image ${index + 1}`}
                loading="lazy"
                onError={(e) => {
                  const target = e.target as HTMLImageElement;
                  target.onerror = null;
                  target.src = "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='100' height='100' viewBox='0 0 100 100'%3E%3Crect width='100' height='100' fill='%23f1f1f1'/%3E%3Ctext x='50%' y='50%' font-size='12' text-anchor='middle' alignment-baseline='middle' font-family='Arial, sans-serif'%3EImage failed to load%3C/text%3E%3C/svg%3E";
                }}
              />
            </div>
          ))}
        </div>
      </ScrollArea>
    </div>
  );
};

const MarkdownComponents: Record<string, React.ComponentType<any>> = {
  h1: ({ children }) => <h1 className="text-2xl font-bold mb-4">{children}</h1>,
  h2: ({ children }) => <h2 className="text-xl font-bold mb-3">{children}</h2>,
  h3: ({ children }) => <h3 className="text-lg font-bold mb-3">{children}</h3>,
  p: ({ children }) => <p className="mb-4 last:mb-0">{children}</p>,
  ul: ({ children }) => <ul className="list-disc ml-6 mb-4">{children}</ul>,
  ol: ({ children }) => <ol className="list-decimal ml-6 mb-4">{children}</ol>,
  li: ({ children }) => <li className="mb-1">{children}</li>,
  code: ({ node, inline, className, children, ...props }) => {
    const match = /language-(\w+)/.exec(className || "");
    const language = match ? match[1] : "";

    return Object.keys(node.properties).length === 0 ? (
      <code className="bg-muted px-1 py-0.5 rounded-md text-sm" {...props}>
        {children}
      </code>
    ) : (
      <ScrollArea className="w-full max-w-full">
        <SyntaxHighlighter
          style={oneDark}
          language={language || "text"}
          PreTag="div"
          className="rounded-md my-2 text-sm"
          showLineNumbers
          customStyle={{
            margin: 0,
            borderRadius: "0.5rem",
            padding: "1rem",
          }}
          {...props}>
          {String(children).replace(/\n$/, "")}
        </SyntaxHighlighter>
      </ScrollArea>
    );
  },
  pre: ({ children }) => <div className="bg-transparent p-0 max-w-full">{children}</div>,
  a: ({ children, href }) => (
    <a href={href} className="text-primary hover:underline" target="_blank" rel="noopener noreferrer">
      {children}
    </a>
  ),
  blockquote: ({ children }) => <blockquote className="border-l-4 border-border pl-4 italic my-4">{children}</blockquote>,
  table: ({ children }) => (
    <div className="overflow-x-scroll border rounded-2xl my-4">
      <table className="w-max border-collapse rounded-2xl overflow-hidden shadow-sm">{children}</table>
    </div>
  ),
  thead: ({ children }) => <thead className="bg-muted">{children}</thead>,
  tbody: ({ children }) => <tbody>{children}</tbody>,
  th: ({ children }) => <th className="border-r last:border-r-0 border-slate-900 px-2 py-1 text-left font-semibold">{children}</th>,
  tr: ({ children }) => <tr className="border-b last:border-b-0 border-border">{children}</tr>,
  td: ({ children }) => <td className="border-r last:border-r-0 border-border px-2 py-1">{children}</td>,
};

interface MessageProps {
  message: MessageType;
  isLoading?: boolean;
  connectionMode: "agent" | "workflow";
}

const Message = ({ message, isLoading, connectionMode }: MessageProps) => {
  const isUser = message?.role === "user";
  const [imageUrls, setImageUrls] = useState<string[]>([]);
  const progressPercentage = message.progress || 0;
  const isProgressMessage = message.isProgress === true && connectionMode === "workflow";
  const [isSearchMessage, setIsSearchMessage] = useState(message.content.startsWith("s_"));

  // Use useMemo to extract sources only once and only when they change
  const sourceLinks = useMemo(() => {
    // If this is the loading component, return empty sources
    if (isLoading) return [];

    // First, extract sources from the research_tree if available
    const researchSources = extractAllSources(message.research_tree);

    // If research_tree sources exist, use those
    if (researchSources.length > 0) {
      return researchSources;
    }

    // Otherwise, fall back to any links in the media object
    return message.media?.links || [];
  }, [message.research_tree, message.media?.links, isLoading]);

  // Extract image URLs from the message content or use the media object
  useEffect(() => {
    if (isLoading) {
      setImageUrls([]);
      return;
    }

    if (!isUser) {
      // Handle image URLs
      let urls: string[] = [];

      // First, check if there's a media object with images
      if (message.media?.images && message.media.images.length > 0) {
        urls = message.media.images;
      }
      setImageUrls(urls);
    }

    setIsSearchMessage(message.content.startsWith("s_"));
  }, [message.content, message.media, isUser, isLoading]);

  const copyToClipboard = () => {
    if (!isLoading) {
      navigator.clipboard.writeText(message.content);
    }
  };

  return (
    <div className="py-2 px-2 sm:px-4 sm:mx-12">
      <div className={`w-full flex gap-4 relative ${isUser ? "justify-end" : "justify-start"}`}>
        <Avatar className={`h-8 w-8 rounded-full bg-muted flex justify-center item-center absolute ${isUser ? "right-0 sm:-right-12" : "left-0 sm:-left-12"} top-0 hidden sm:flex`}>{isLoading || isProgressMessage ? <Loader2 className="h-full w-6 animate-spin" /> : isUser ? <User2 className="h-full w-6" /> : <Bot className="h-full w-6" />}</Avatar>

        <div className={`max-w-full ${isLoading || isProgressMessage ? "w-[80%]" : ""} ${isUser ? "items-end ml-auto" : "items-start mr-auto"}`}>
          <div className={`flex items-center gap-2 mb-1 ${isUser ? "justify-end" : "justify-start"}`}>
            <div className="font-medium">{isUser ? "You" : "KNet"}</div>
            {!isUser && !isLoading && <div className="text-xs text-muted-foreground">{new Date(message.timestamp).toLocaleTimeString()}</div>}
            {(isLoading || isProgressMessage) && connectionMode === "workflow" && <div className="text-xs text-muted-foreground">Just now</div>}

            {!isUser && !isLoading && !isProgressMessage && (
              <div className="ml-auto flex items-center gap-2">
                <TooltipProvider>
                  <Tooltip>
                    <TooltipTrigger asChild>
                      <Button size="icon" variant="ghost" className="h-8 w-8" onClick={copyToClipboard}>
                        <Copy className="h-4 w-4" />
                      </Button>
                    </TooltipTrigger>
                    <TooltipContent>Copy to clipboard</TooltipContent>
                  </Tooltip>
                </TooltipProvider>

                <DropdownMenu>
                  <DropdownMenuTrigger asChild>
                    <Button size="icon" variant="ghost" className="h-8 w-8">
                      <MoreHorizontal className="h-4 w-4" />
                    </Button>
                  </DropdownMenuTrigger>
                  <DropdownMenuContent align="end">
                    <DropdownMenuItem onClick={copyToClipboard}>Copy text</DropdownMenuItem>
                    <DropdownMenuItem>Show sources</DropdownMenuItem>
                    <DropdownMenuItem>View in visualizations</DropdownMenuItem>
                  </DropdownMenuContent>
                </DropdownMenu>
              </div>
            )}
          </div>

          <div className={`mt-1 w-full ${isUser ? "bg-slate-300 dark:bg-slate-200 dark:text-background text-foreground" : "bg-muted/50"} p-3 rounded-2xl ${isUser ? "rounded-tr-sm" : "rounded-tl-sm"}`} style={{ overflowWrap: "anywhere" }}>
            {(isLoading || isProgressMessage) && connectionMode === "workflow" ? (
              <div className="space-y-2">
                <div>{message.content}</div>
                <div className={`flex items-center ${isSearchMessage ? "justify-between" : "justify-end"} text-sm w-full`}>
                  {isSearchMessage ? (
                    <Badge variant="outline" className="bg-primary/20 text-primary rounded-full">
                      <SearchIcon className="h-3 w-3 mr-1" />
                      {message.content.slice(2)}
                    </Badge>
                  ) : null}
                  <Badge variant="outline" className="ml-2 bg-primary/20 text-primary">
                    {progressPercentage}%
                  </Badge>
                </div>
                <div className="w-full bg-muted/30 h-2.5 rounded-full overflow-hidden">
                  <div className="h-full bg-primary transition-all duration-500 rounded-full flex items-center justify-end" style={{ width: `${progressPercentage}%` }}>
                    <div className="h-2 w-2 rounded-full bg-primary-foreground mr-0.5 animate-pulse"></div>
                  </div>
                </div>
              </div>
            ) : (
              <>
                {message.content && message.content.trim() !== "" && (
                  <ReactMarkdown remarkPlugins={[remarkGfm]} components={MarkdownComponents}>
                    {message.content}
                  </ReactMarkdown>
                )}

                {message.tool_calls && message.tool_calls.length > 0 && (
                  <div className={`${message.content && message.content.trim() !== "" ? "mt-3" : ""} space-y-2`}>
                    <div className="text-xs font-medium text-muted-foreground uppercase tracking-wider mb-1">Tool Usage</div>
                    {message.tool_calls.map((toolCall, index) => (
                      <ToolCallDisplay key={index} toolCall={toolCall} />
                    ))}
                  </div>
                )}

                {sourceLinks.length > 0 && <SourceLinks links={sourceLinks} />}
                {imageUrls.length > 0 && <ImageGallery imageUrls={imageUrls} />}
              </>
            )}
          </div>
        </div>
      </div>
    </div>
  );
};

export default Message;
