type Listener = () => void;

export function createState<T>(initialValue: T) {
  let value = initialValue;
  const listeners = new Set<Listener>();

  function setState(newValue: T): void {
    if (newValue !== value) {
      value = newValue;
      listeners.forEach(listener => listener());
    }
  }

  function getState(): T {
    return value;
  }

  function subscribe(listener: Listener): () => void {
    if (typeof listener !== 'function') {
      throw new Error('El listener debe ser una función');
    }
    listeners.add(listener);

    // Devuelve una función que permitirá desuscribirse
    return () => listeners.delete(listener);
  }

  return [getState, setState, subscribe] as const;
}


// Función para crear un elemento con JSX
export function jsx(type: string, props: { [key: string]: any }, ...children: any[]): HTMLElement {
  if (typeof type !== 'string') {
    throw new Error('El tipo del elemento debe ser una cadena');
  }

  const el = document.createElement(type);

  if (props) {
    Object.keys(props).forEach((key) => {
      if (key.startsWith('on')) {
        const event = key.substring(2).toLowerCase();
        if (typeof props[key] === 'function') {
          el.addEventListener(event, props[key]);
        } else {
          console.warn(`El manejador del evento ${event} no es una función.`);
        }
      } else if (key === 'className') {
        el.classList.add(props[key]);
      } else {
        el.setAttribute(key, props[key]);
      }
    });
  }

  children.forEach((child) => {
    if (typeof child === 'string') {
      el.appendChild(document.createTextNode(child));
    } else if (child instanceof HTMLElement) {
      el.appendChild(child);
    }
  });

  return el;
}

// Función para renderizar un componente en un contenedor
// Función para renderizar un componente en un contenedor
// Función para renderizar un componente en un contenedor
export function render(component: () => { element: HTMLElement, subscribe: (listener: () => void) => () => void }, container: HTMLElement): () => void {
  if (!container || !(container instanceof HTMLElement)) {
    throw new Error('El contenedor debe ser un elemento DOM válido');
  }

  function update(): void {
    const { element } = component();  // Obtener el componente renderizado
    container.innerHTML = '';         // Limpiar el contenedor
    container.appendChild(element);   // Añadir el componente al contenedor
  }

  update();  // Primer renderizado

  // La función subscribe devuelve una función para desuscribirse
  const unsubscribe = component().subscribe(update); // Suscribirse al estado

  return () => {
    update();
    unsubscribe(); // Desuscribirse cuando sea necesario
  };
}

