import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
import { PrimariaNotificationServiceImpl } from "./notification.service-impl";

describe("PrimariaNotificationServiceImpl", () => {
  let service: PrimariaNotificationServiceImpl;

  beforeEach(() => {
    service = new PrimariaNotificationServiceImpl();
    document.body.innerHTML = ""; // limpia el DOM antes de cada test
    vi.useFakeTimers(); // usamos timers falsos para testear setTimeout
  });

  afterEach(() => {
    vi.clearAllTimers();
    vi.useRealTimers();
  });

  const assertToast = (expectedState: string, message: string, duration: number = 3000) => {
    const toast = document.querySelector("dss-toast") as HTMLElement;
    expect(toast).not.toBeNull();
    expect(toast.getAttribute("isshow")).toBe("true");
    expect(toast.getAttribute("state")).toBe(expectedState);
    expect(toast.getAttribute("position")).toBe("bottom-left");
    expect(toast.getAttribute("text")).toBe(message);
    expect(toast.getAttribute("hasicon")).toBe("true");
    expect(toast.getAttribute("duration")).toBe(duration.toString());
  };

  it.each([
    ["info", "info"],
    ["warning", "warning"],
    ["error", "error"],
    ["success", "success"],
  ] as const)("should create a '%s' toast", (method, state) => {
    const message = `Test ${state}`;
    (service[method] as any)(message);
    assertToast(state, message);
  });

  it("should create a container for toasts", () => {
    service.info("Test");
    const container = document.getElementById("primaria-toast-container");
    expect(container).not.toBeNull();
    expect(container?.style.position).toBe("fixed");
  });

  it("should remove the toast after the duration", () => {
    service.info("Temporary toast", 2000);

    let toast = document.querySelector("dss-toast") as HTMLElement;
    expect(toast).not.toBeNull();
    expect(toast.getAttribute("isshow")).toBe("true");

    // Avanza el primer timeout (esconde el toast)
    vi.advanceTimersByTime(2000);
    expect(toast.getAttribute("isshow")).toBe("false");

    // Avanza el segundo timeout (remueve del DOM)
    vi.advanceTimersByTime(300);
    toast = document.querySelector("dss-toast") as HTMLElement;
    expect(toast).toBeNull();
  });

  it("should remove the container when all toasts are dismissed", () => {
    service.info("Toast 1", 1000);

    vi.advanceTimersByTime(1000);
    vi.advanceTimersByTime(300);

    const container = document.getElementById("primaria-toast-container");
    expect(container).toBeNull();
  });

  it("should stack multiple toasts in the same container", () => {
    service.info("Toast 1");
    service.warning("Toast 2");
    service.error("Toast 3");

    const container = document.getElementById("primaria-toast-container");
    const toasts = container?.querySelectorAll("dss-toast");
    expect(toasts?.length).toBe(3);
  });
});
