import { BlogPost } from "@/components/blog/types";
import { clsx, type ClassValue } from "clsx";
import { twMerge } from "tailwind-merge";

export function cn(...inputs: ClassValue[]) {
  return twMerge(clsx(inputs));
}
export function truncateHtmlPreservingTags(html: string, maxWords: number) {
  if (typeof document === "undefined") {
    const words = html
      .replace(/<[^>]+>/g, "")
      .trim()
      .split(/\s+/);
    return words.length > maxWords ? words.slice(0, maxWords).join(" ") + "…" : html;
  }

  const div = document.createElement("div");
  div.innerHTML = html;

  let wordCount = 0;
  let reachedLimit = false;

  function traverse(node: Node): Node | null {
    if (reachedLimit) return null;

    if (node.nodeType === Node.TEXT_NODE) {
      const text = node.textContent || "";
      const words = text.trim().split(/\s+/);

      if (wordCount + words.length <= maxWords) {
        wordCount += words.length;
        return document.createTextNode(text);
      }

      const remaining = maxWords - wordCount;
      const truncated = words.slice(0, remaining).join(" ") + "…";
      reachedLimit = true;
      return document.createTextNode(truncated);
    }

    if (node.nodeType === Node.ELEMENT_NODE) {
      const element = node as HTMLElement;
      const clone = element.cloneNode(false) as HTMLElement;

      for (const child of Array.from(node.childNodes)) {
        if (reachedLimit) break;
        const newChild = traverse(child);
        if (newChild) clone.appendChild(newChild);
      }

      return clone;
    }

    return null;
  }

  const result = traverse(div);

  if (result && result instanceof Element) return result.innerHTML;

  return "";
}
export const timeOut = (t: number) =>
  new Promise<void>((resolve) => {
    setTimeout(() => {
      resolve();
    }, t);
  });

export const getAfterEquals = (value: string) => {
  const index = value.indexOf("=");
  if (index === -1) return "";
  return value.slice(index + 1).trim();
};

/**
 *
 * @param numeroStr Un string que sé que es un número
 * @returns el número formateado
 * @example 1234567 -> 1.234.567
 */
export function formatNumber(numeroStr: string): string {
  const numero = parseInt(numeroStr);
  return numero.toLocaleString("es-ES");
}
/**
 * Convierte un timestamp a formato "Día de semana, día de mes año"
 * @param timestamp un datetime que llegue desde el back o un Date.now()
 * @returns string con fecha formateada al español
 * @example "Lunes, 15 de diciembre del 2025"
 */
export function formatTimestampToSpanishDate(timestamp: number | string | Date, post = false): string {
  const date = new Date(timestamp);

  if (isNaN(date.getTime())) {
    throw new Error("Timestamp no válido");
  }

  // Nombres de días y meses en español
  const diasSemana = ["Domingo", "Lunes", "Martes", "Miércoles", "Jueves", "Viernes", "Sábado"];

  const meses = [
    "enero",
    "febrero",
    "marzo",
    "abril",
    "mayo",
    "junio",
    "julio",
    "agosto",
    "septiembre",
    "octubre",
    "noviembre",
    "diciembre",
  ];

  const diaSemana = diasSemana[date.getDay()];
  const diaMes = date.getDate();
  const mes = meses[date.getMonth()];
  const año = date.getFullYear();

  return `${diaSemana}, ${diaMes} ${post ? "de" : ""}  ${mes} ${post ? "del" : ""} ${año}`;
}
export const getFeaturedPost = (posts: BlogPost[]) => {
  if (!posts || !posts.length) return;
  return posts.find((post) => post.is_recommended) || posts[0];
};

export const formatPlanWords = (input: string): string[] =>
  input
    .toLowerCase()
    .split(" ")
    .filter(Boolean)
    .map((word) => word.charAt(0).toUpperCase() + word.slice(1));
