import van from "./van.js";
const { button, div, span, h1, img, p, input } = van.tags;

import markdownit from "https://cdn.jsdelivr.net/npm/markdown-it@14.1.0/+esm";
import hljs from "https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/es/highlight.min.js";

// Markdown configuration (matching the HTML)
const md = markdownit({
  html: true,
  linkify: true,
  typographer: true,
  highlight: function (str, lang) {
    if (lang && hljs.getLanguage(lang)) {
      try {
        return hljs.highlight(str, { language: lang }).value;
      } catch (__) {}
    }

    return ""; // use external default escaping
  },
});

export const messages = van.state([]);
export const users = van.state({});

// Helper function to render Markdown
function renderMarkdown(text) {
  return md.render(text);
}

// Component for a single message
function Message(message) {
  const userName = users[message.user_id] || "Unknown User"; // Get username from state or default

  const content = div({ class: "message-text" });
  content.innerHTML = renderMarkdown(message.text);

  return div(
    { class: "message" },
    img({ class: "user-avatar", src: `cdn/profile/${message.user_id}` }),
    div(
      { class: "message-content" },
      div(
        { class: "message-header" },
        span({ class: "username" }, userName),
        span(
          { class: "timestamp" },
          new Date(message.timestamp).toLocaleTimeString("en-GB"),
        ),
      ),
      content, // Render Markdown here
    ),
  );
}

// Component for the entire chat interface
function ChatApp() {
  return div(
    { class: "chat-container" },
    div(
      { class: "chat-header" },
      div(
        { class: "chat-title" },
        img({ class: "user-avatar", src: "cdn/profile/0" }),
        h1(null, "Wish.com Discord frfr"),
      ),
    ),

    van.derive(() => {
      console.log("Deriving messages");
      const container = div({ class: "messages-container" });

      for (const message of messages.val) {
        van.add(container, Message(message));
      }
      return container;
    }),

    div(
      { class: "input-container" },
      div(
        { class: "input-wrapper" },
        input({ type: "text", placeholder: "Start Typing..." }),
        button(
          { class: "send-button", onclick: () => sendMessage() },
          img({ src: "cdn/icons/send.svg" }),
        ),
      ),
    ),
  );
}

async function sendMessage() {
  const messageInput = document.querySelector(".input-wrapper input");
  const message = messageInput.value.trim();

  if (message) {
    await fetch("/api/chat/", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({
        user_id: user_id,
        text: message,
        timestamp: new Date().getTime(),
      }),
    });

    messageInput.value = "";
  }
}

// Function to fetch user data (replace with your actual API endpoint)
async function fetchUsers() {
  try {
    const userIds = await fetch("/api/users/").then((r) => r.json());

    const userPromises = userIds.map((userId) =>
      fetch(`/api/users/${userId}`)
        .then((r) => r.text())
        .then((username) => ({ userId, username })),
    );

    const userData = await Promise.all(userPromises);

    userData.forEach(({ userId, username }) => {
      users.val[userId] = username;
    });
  } catch (error) {
    console.error("Error fetching users:", error);
  }
}

// Function to handle incoming messages from SSE
function handleSSEMessage(event) {
  let message = JSON.parse(event.data);
  messages.val = [...messages.val, message];
}

// Initialize the application
async function init() {
  await fetchUsers();

  const eventSource = new EventSource("/api/events"); // Replace with your SSE endpoint

  eventSource.onopen = () => console.log("SSE connection opened");
  eventSource.onmessage = handleSSEMessage;
  eventSource.onerror = (error) => {
    console.error("EventSource error:", error);
    // Attempt to reconnect after a delay
    setTimeout(() => eventSource.open(), 5000);
  };

  van.add(document.body, ChatApp());
}

init();
