import { RefObject, useEffect, useRef, useSyncExternalStore, type ReactElement } from "react";
import { user, message } from "@localtypes";
import { subscribeUsers, getUsers, subscribeMessages, getMessages, self } from "@ws";

function formatUnixTimestamp(ts: number) {
  const date = new Date(ts);
  const now = new Date();

  const isToday =
    date.getDate() === now.getDate() &&
    date.getMonth() === now.getMonth() &&
    date.getFullYear() === now.getFullYear();
  const HH = String(date.getHours()).padStart(2, '0');
  const min = String(date.getMinutes()).padStart(2, '0');
  if (isToday) {
    return `Today at ${HH}:${min}`;
  }
  const dd = String(date.getDate()).padStart(2, '0');
  const mm = String(date.getMonth() + 1).padStart(2, '0');
  const yy = String(date.getFullYear())
  return `${dd}/${mm}/${yy} ${HH}:${min}`;
}

export function RenderMessages(): ReactElement {
  let currentAuthor: user | null = null;
  const messages: (message | null)[] = useSyncExternalStore(
    subscribeMessages,
    getMessages
  );

  console.log(messages);

  const bottomRef = useRef<HTMLDivElement | null>(null);

  useEffect(() => {
    bottomRef.current?.scrollIntoView({ behavior: "instant" });
  }, [messages.length]);

  return (
    <div className="messages">
      {messages.map((message, index) => {
        if (message) {
          const nextMessage = messages[index + 1];
          const nextAuthor = nextMessage ? nextMessage.author : null;
          const isLastMessageFromAuthor = nextAuthor?.id !== message.author.id;
          const inline = currentAuthor?.id === message.author.id;
          if (!inline) {
            currentAuthor = message.author;
          }

          return (
            <Message
              key={message.id}
              author={message.author}
              content={message.content}
              inline={inline}
              bottom={isLastMessageFromAuthor}
              timestamp={message.timestamp}
              hasSent={message.hasSent}
              mention={message.content.includes(`<@${self.id}>`) || message.content.includes("@everyone") || message.content.includes("@here")}
            />
          );
        } else return ""
      })}
      <div ref={bottomRef} />
    </div>
  );
}

function Message({author, content, inline = false, bottom = false, timestamp = 0, hasSent, mention}: {author: user, content: string, inline?: boolean, bottom?: boolean, timestamp?: number, hasSent: boolean, mention: boolean}): ReactElement {
  const users: user[] = useSyncExternalStore(
    subscribeUsers,
    getUsers
  );

  function formatContent(content: string): ReactElement[] {
    const parts = content.split('\n'); // Split the content into parts by newlines

    return parts.flatMap((part, index) => {
      const elements: ReactElement[] = [];
      let lastIndex = 0;

      // Match all mentions in the part (e.g., <@123>)
      const mentionRegex = /<@(\d+)>/g;
      let match;

      while ((match = mentionRegex.exec(part)) !== null) {
        const [mentionTag, userId] = match;
        const textBeforeMention = part.slice(lastIndex, match.index);

        // Add the text before the mention as plain text
        if (textBeforeMention) {
          elements.push(<span key={`${index}-text-${lastIndex}`}>{textBeforeMention}</span>);
        }

        // Add the Mention component
        const user = users.find((user) => user.id === parseInt(userId!)); // Use parseInt for ID comparison
        elements.push(
          <Mention
            key={`${index}-mention-${userId}`}
            name={user?.name}
            username={user ? user.username : 'unknown-user'}
          />
        );

        lastIndex = mentionRegex.lastIndex; // Update the last index
      }

      // Add any remaining text after the last mention (if any)
      const remainingText = part.slice(lastIndex);
      if (remainingText) {
        elements.push(<span key={`${index}-text-${lastIndex}`}>{remainingText}</span>);
      }

      // Add a <br /> between parts if it’s not the last part
      if (index < parts.length - 1) {
        elements.push(<br key={`br-${index}`} />);
      }

      return elements;
    });
  }
  const formattedContent = formatContent(content);

  return (
    <div className={`message ${inline ? "inline" : ""} ${bottom ? "bottom" : ""} ${hasSent ? "" : "sending"} ${mention ? "mentionsyou" : ""}`}>
      {!inline ? <img className="messagePfp" src={`/pfps/${author.pfp}.png`} width={48} height={48}></img> : ""}
      {!inline ? <div className="messageAuthor"><span>{self.dev ? `${author.name} (${author.username}, ${author.id})` : author.name ?? author.username}</span> {author.dev ? <Badge text="DEV" /> : ""} <Timestamp ts={timestamp} /></div> : ""}
      <div className="messageContent">{formattedContent}</div>
    </div>
  )
}

function Badge({text, color = "#a200ff"}: {text: string, color?: string}) {
  return (
    <div className="badge" style={{["--badge-color" as any]: color ?? "var(--brand-color)"}}>{text}</div>
  )
}

function Timestamp({ts}: {ts: number}): ReactElement {
  return (
    <div className="messageTimestamp">{formatUnixTimestamp(ts)}</div>
  )
}

function Mention({name, username}: { name?: string, username: string }): ReactElement {
  return (
    <div className="mention">@{name ?? username}</div>
  )
}