import { describe, it, expect } from "vitest";
import {
  escapeHtml,
  buildResetEmail,
  buildContactEmail,
} from "../email-service.js";

describe("email-service", () => {
  // ────────────── escapeHtml ──────────────

  describe("escapeHtml", () => {
    it("échappe le caractère &", () => {
      expect(escapeHtml("a&b")).toBe("a&amp;b");
    });

    it("échappe le caractère <", () => {
      expect(escapeHtml("a<b")).toBe("a&lt;b");
    });

    it("échappe le caractère >", () => {
      expect(escapeHtml("a>b")).toBe("a&gt;b");
    });

    it('échappe le caractère "', () => {
      expect(escapeHtml('a"b')).toBe("a&quot;b");
    });

    it("échappe le caractère '", () => {
      expect(escapeHtml("a'b")).toBe("a&#39;b");
    });

    it("échappe tous les caractères spéciaux ensemble", () => {
      expect(escapeHtml('<script>alert("xss")</script>')).toBe(
        "&lt;script&gt;alert(&quot;xss&quot;)&lt;/script&gt;",
      );
    });

    it("ne modifie pas une chaîne sans caractères spéciaux", () => {
      expect(escapeHtml("Hello World 123")).toBe("Hello World 123");
    });

    it("gère une chaîne vide", () => {
      expect(escapeHtml("")).toBe("");
    });

    it("échappe les multiples occurrences", () => {
      expect(escapeHtml("a&b&c")).toBe("a&amp;b&amp;c");
    });
  });

  // ────────────── buildResetEmail ──────────────

  describe("buildResetEmail", () => {
    it("retourne subject, text et html", () => {
      const result = buildResetEmail({
        email: "test@example.com",
        token: "abc123",
      });
      expect(result.subject).toBe("Reinitialisation de mot de passe");
      expect(result.text).toContain("abc123");
      expect(result.html).toContain("abc123");
    });

    it("inclut le lien de reset si appUrl est fourni", () => {
      const result = buildResetEmail({
        email: "test@example.com",
        token: "tok123",
        appUrl: "https://rollerlogic.com",
      });
      expect(result.text).toContain(
        "https://rollerlogic.com/reset-password?token=tok123",
      );
      expect(result.html).toContain(
        "https://rollerlogic.com/reset-password?token=tok123",
      );
    });

    it("supprime le trailing slash de appUrl", () => {
      const result = buildResetEmail({
        email: "test@example.com",
        token: "tok",
        appUrl: "https://example.com/",
      });
      expect(result.text).toContain(
        "https://example.com/reset-password?token=tok",
      );
    });

    it("utilise le nom personnalisé si fromName est fourni", () => {
      const result = buildResetEmail({
        email: "test@example.com",
        token: "tok",
        fromName: "MonJeu",
      });
      expect(result.text).toContain("Equipe MonJeu");
      expect(result.html).toContain("Equipe MonJeu");
    });

    it("utilise le nom par défaut si fromName est absent", () => {
      const result = buildResetEmail({
        email: "test@example.com",
        token: "tok",
      });
      expect(result.text).toContain("L'equipe RollerLogic");
    });

    it("contient le token dans le texte brut", () => {
      const result = buildResetEmail({
        email: "test@example.com",
        token: "myToken",
      });
      expect(result.text).toContain("Token: myToken");
      expect(result.html).toContain("myToken");
    });
  });

  // ────────────── buildContactEmail ──────────────

  describe("buildContactEmail", () => {
    const basePayload = {
      userId: 42,
      email: "user@example.com",
      displayName: "Joueur Test",
      message: "Bonjour, j'ai un problème",
    };

    it("retourne subject, text et html", () => {
      const result = buildContactEmail(basePayload);
      expect(result.subject).toContain("[Contact]");
      expect(result.text).toContain("Joueur Test");
      expect(result.html).toContain("Joueur Test");
    });

    it("utilise le sujet par défaut si non fourni", () => {
      const result = buildContactEmail(basePayload);
      expect(result.subject).toBe("[Contact] Contact RollerLogic");
    });

    it("utilise le sujet personnalisé si fourni", () => {
      const result = buildContactEmail({
        ...basePayload,
        subject: "Bug critique",
      });
      expect(result.subject).toBe("[Contact] Bug critique");
    });

    it("inclut l'email et le userId dans le texte", () => {
      const result = buildContactEmail(basePayload);
      expect(result.text).toContain("user@example.com");
      expect(result.text).toContain("42");
    });

    it("inclut le message dans le texte", () => {
      const result = buildContactEmail(basePayload);
      expect(result.text).toContain("Bonjour, j'ai un problème");
    });

    it("inclut l'IP si fournie", () => {
      const result = buildContactEmail({ ...basePayload, ip: "192.168.1.1" });
      expect(result.text).toContain("192.168.1.1");
      expect(result.html).toContain("192.168.1.1");
    });

    it("inclut le User-Agent si fourni", () => {
      const result = buildContactEmail({
        ...basePayload,
        userAgent: "Mozilla/5.0",
      });
      expect(result.text).toContain("Mozilla/5.0");
    });

    it("tronque le User-Agent à 100 caractères dans le HTML", () => {
      const longUA = "A".repeat(150);
      const result = buildContactEmail({ ...basePayload, userAgent: longUA });
      expect(result.html).toContain("...");
    });

    it("échappe le HTML dans le displayName", () => {
      const result = buildContactEmail({
        ...basePayload,
        displayName: '<script>alert("xss")</script>',
      });
      expect(result.html).toContain("&lt;script&gt;");
      expect(result.html).not.toContain("<script>");
    });

    it("échappe le HTML dans le message", () => {
      const result = buildContactEmail({
        ...basePayload,
        message: '<img src="x" onerror="alert(1)">',
      });
      expect(result.html).not.toContain('<img src="x"');
    });

    it("ne contient pas d'IP si non fournie", () => {
      const result = buildContactEmail(basePayload);
      expect(result.text).not.toContain("IP:");
    });
  });
});
