import { describe, test, expect } from "bun:test";
import { htmlToPlainText, truncate, emailPreview } from "./utils";

describe("htmlToPlainText", () => {
  test("strips simple HTML tags", () => {
    expect(htmlToPlainText("<p>Hello <b>world</b></p>")).toBe("Hello world");
  });

  test("converts <br> to newlines", () => {
    expect(htmlToPlainText("line1<br>line2<br/>line3")).toBe(
      "line1\nline2\nline3",
    );
  });

  test("converts block elements to newlines", () => {
    expect(htmlToPlainText("<p>para1</p><p>para2</p>")).toBe("para1\npara2");
  });

  test("decodes HTML entities", () => {
    expect(htmlToPlainText("&amp; &lt; &gt; &quot; &#39; &nbsp;")).toBe(
      '& < > " \'',
    );
  });

  test("decodes numeric entities", () => {
    expect(htmlToPlainText("&#65;&#66;&#67;")).toBe("ABC");
  });

  test("collapses excessive newlines", () => {
    const input = "<p>a</p><p></p><p></p><p></p><p>b</p>";
    const result = htmlToPlainText(input);
    expect(result.split("\n").length).toBeLessThanOrEqual(4);
  });

  test("handles empty string", () => {
    expect(htmlToPlainText("")).toBe("");
  });

  test("handles plain text passthrough", () => {
    expect(htmlToPlainText("just plain text")).toBe("just plain text");
  });

  test("handles <hr> tags", () => {
    expect(htmlToPlainText("above<hr>below")).toBe("above\n---\nbelow");
  });

  test("handles complex email HTML", () => {
    const html = `
      <html><body>
        <div>Hi Gautam,</div>
        <div><br></div>
        <div>Your appointment is confirmed for <b>May 1st at 2pm</b>.</div>
        <div><br></div>
        <div>Best regards,<br>Dr. Smith</div>
      </body></html>
    `;
    const text = htmlToPlainText(html);
    expect(text).toContain("Hi Gautam,");
    expect(text).toContain("appointment is confirmed");
    expect(text).toContain("May 1st at 2pm");
    expect(text).toContain("Dr. Smith");
    expect(text).not.toContain("<");
  });
});

describe("truncate", () => {
  test("returns short strings unchanged", () => {
    expect(truncate("hello", 10)).toBe("hello");
  });

  test("truncates long strings with ellipsis", () => {
    expect(truncate("hello world", 8)).toBe("hello...");
  });

  test("handles exact length", () => {
    expect(truncate("hello", 5)).toBe("hello");
  });

  test("handles very short maxLen", () => {
    expect(truncate("hello", 3)).toBe("...");
  });
});

describe("emailPreview", () => {
  test("collapses newlines to single line", () => {
    expect(emailPreview("line1\nline2\nline3")).toBe("line1 line2 line3");
  });

  test("truncates to default 120 chars", () => {
    const long = "a".repeat(200);
    const preview = emailPreview(long);
    expect(preview.length).toBe(120);
    expect(preview.endsWith("...")).toBe(true);
  });

  test("respects custom maxLen", () => {
    const preview = emailPreview("hello world foo bar", 10);
    expect(preview.length).toBe(10);
  });
});
