function escapeHtml(text: string): string {
  const div = document.createElement("div");
  div.textContent = text;
  return div.innerHTML;
}

function querySelector<T extends Element>(selector: string): T | null {
  return document.querySelector<T>(selector);
}

function querySelectorAll<T extends Element>(selector: string): NodeListOf<T> {
  return document.querySelectorAll<T>(selector);
}

function getElementById<T extends HTMLElement>(id: string): T | null {
  return document.getElementById(id) as T | null;
}

function createElement<K extends keyof HTMLElementTagNameMap>(
  tagName: K,
  attributes?: Record<string, string>,
  children?: (string | Node)[],
): HTMLElementTagNameMap[K] {
  const element = document.createElement(tagName);

  if (attributes) {
    Object.entries(attributes).forEach(([key, value]) => {
      if (key === "className") {
        element.className = value;
      } else if (key === "dataset") {
        Object.entries(JSON.parse(value)).forEach(([dataKey, dataValue]) => {
          element.dataset[dataKey] = String(dataValue);
        });
      } else {
        element.setAttribute(key, value);
      }
    });
  }

  if (children) {
    children.forEach((child) => {
      if (typeof child === "string") {
        element.appendChild(document.createTextNode(child));
      } else {
        element.appendChild(child);
      }
    });
  }

  return element;
}

function showElement(element: HTMLElement | null): void {
  if (element) {
    element.classList.remove("hidden");
  }
}

function hideElement(element: HTMLElement | null): void {
  if (element) {
    element.classList.add("hidden");
  }
}

function toggleElement(element: HTMLElement | null): void {
  if (element) {
    element.classList.toggle("hidden");
  }
}

function setTextContent(element: HTMLElement | null, text: string): void {
  if (element) {
    element.textContent = text;
  }
}

function setInnerHTML(element: HTMLElement | null, html: string): void {
  if (element) {
    element.innerHTML = html;
  }
}

function addClass(element: HTMLElement | null, className: string): void {
  if (element) {
    element.classList.add(className);
  }
}

function removeClass(element: HTMLElement | null, className: string): void {
  if (element) {
    element.classList.remove(className);
  }
}

function toggleClass(element: HTMLElement | null, className: string): void {
  if (element) {
    element.classList.toggle(className);
  }
}

function hasClass(element: HTMLElement | null, className: string): boolean {
  return element ? element.classList.contains(className) : false;
}

export {
  addClass,
  createElement,
  escapeHtml,
  getElementById,
  hasClass,
  hideElement,
  querySelector,
  querySelectorAll,
  removeClass,
  setInnerHTML,
  setTextContent,
  showElement,
  toggleClass,
  toggleElement,
};
