/**
 * Blockquote Spacing Tests
 *
 * Per CommonMark spec (§5.1 Block quotes), blockquotes are "container blocks" that
 * contain other block-level elements (paragraphs, code blocks, etc.).
 *
 * In plaintext rendering, the expected spacing between block-level elements is
 * a single blank line (double newline `\n\n`). This is the standard paragraph
 * separation used throughout markdown.
 *
 * CORRECT behavior:
 *   - Blockquote content followed by paragraph: "quote\n\nparagraph" (double \n)
 *   - Two consecutive blockquotes: "first\n\nsecond" (double \n)
 *
 * BUG (current behavior):
 *   - Produces triple newlines: "quote\n\n\nparagraph"
 *
 * Root cause:
 *   1. `paragraph_close` inside blockquote adds `\n\n` (correct)
 *   2. `blockquote_close` adds another `\n` (incorrect)
 *   3. Result: `\n\n\n` (triple newlines - incorrect)
 *
 * The fix: `blockquote_close` should NOT add `\n` because:
 *   - Blockquotes are container blocks, not leaf blocks
 *   - The inner content (paragraph, heading, etc.) already provides block separation
 *   - Container closings shouldn't add their own spacing
 */

import { describe, it, expect } from "vitest";
import { markdownToIR } from "./ir.js";

describe("blockquote spacing", () => {
  describe("blockquote followed by paragraph", () => {
    it("should have double newline (one blank line) between blockquote and paragraph", () => {
      const input = "> quote\n\nparagraph";
      const result = markdownToIR(input);

      // CORRECT: "quote\n\nparagraph" (double newline)
      // BUG: "quote\n\n\nparagraph" (triple newline)
      expect(result.text).toBe("quote\n\nparagraph");
    });

    it("should not produce triple newlines", () => {
      const input = "> quote\n\nparagraph";
      const result = markdownToIR(input);

      expect(result.text).not.toContain("\n\n\n");
    });
  });

  describe("consecutive blockquotes", () => {
    it("should have double newline between two blockquotes", () => {
      const input = "> first\n\n> second";
      const result = markdownToIR(input);

      expect(result.text).toBe("first\n\nsecond");
    });

    it("should not produce triple newlines between blockquotes", () => {
      const input = "> first\n\n> second";
      const result = markdownToIR(input);

      expect(result.text).not.toContain("\n\n\n");
    });
  });

  describe("nested blockquotes", () => {
    it("should handle nested blockquotes correctly", () => {
      const input = "> outer\n>> inner";
      const result = markdownToIR(input);

      // Inner blockquote becomes separate paragraph
      expect(result.text).toBe("outer\n\ninner");
    });

    it("should not produce triple newlines in nested blockquotes", () => {
      const input = "> outer\n>> inner\n\nparagraph";
      const result = markdownToIR(input);

      expect(result.text).not.toContain("\n\n\n");
    });

    it("should handle deeply nested blockquotes", () => {
      const input = "> level 1\n>> level 2\n>>> level 3";
      const result = markdownToIR(input);

      // Each nested level is a new paragraph
      expect(result.text).not.toContain("\n\n\n");
    });
  });

  describe("blockquote followed by other block elements", () => {
    it("should have double newline between blockquote and heading", () => {
      const input = "> quote\n\n# Heading";
      const result = markdownToIR(input);

      expect(result.text).toBe("quote\n\nHeading");
      expect(result.text).not.toContain("\n\n\n");
    });

    it("should have double newline between blockquote and list", () => {
      const input = "> quote\n\n- item";
      const result = markdownToIR(input);

      // The list item becomes "• item"
      expect(result.text).toBe("quote\n\n• item");
      expect(result.text).not.toContain("\n\n\n");
    });

    it("should have double newline between blockquote and code block", () => {
      const input = "> quote\n\n```\ncode\n```";
      const result = markdownToIR(input);

      // Code blocks preserve their trailing newline
      expect(result.text.startsWith("quote\n\ncode")).toBe(true);
      expect(result.text).not.toContain("\n\n\n");
    });

    it("should have double newline between blockquote and horizontal rule", () => {
      const input = "> quote\n\n---\n\nparagraph";
      const result = markdownToIR(input);

      // HR just adds a newline in IR, but should not create triple newlines
      expect(result.text).not.toContain("\n\n\n");
    });
  });

  describe("blockquote with multi-paragraph content", () => {
    it("should handle multi-paragraph blockquote followed by paragraph", () => {
      const input = "> first paragraph\n>\n> second paragraph\n\nfollowing paragraph";
      const result = markdownToIR(input);

      // Multi-paragraph blockquote should have proper internal spacing
      // AND proper spacing with following content
      expect(result.text).toContain("first paragraph\n\nsecond paragraph");
      expect(result.text).not.toContain("\n\n\n");
    });
  });

  describe("blockquote prefix option", () => {
    it("should include prefix and maintain proper spacing", () => {
      const input = "> quote\n\nparagraph";
      const result = markdownToIR(input, { blockquotePrefix: "> " });

      // With prefix, should still have proper spacing
      expect(result.text).toBe("> quote\n\nparagraph");
      expect(result.text).not.toContain("\n\n\n");
    });
  });

  describe("edge cases", () => {
    it("should handle empty blockquote followed by paragraph", () => {
      const input = ">\n\nparagraph";
      const result = markdownToIR(input);

      expect(result.text).not.toContain("\n\n\n");
    });

    it("should handle blockquote at end of document", () => {
      const input = "paragraph\n\n> quote";
      const result = markdownToIR(input);

      // No trailing triple newlines
      expect(result.text).not.toContain("\n\n\n");
    });

    it("should handle multiple blockquotes with paragraphs between", () => {
      const input = "> first\n\nparagraph\n\n> second";
      const result = markdownToIR(input);

      expect(result.text).toBe("first\n\nparagraph\n\nsecond");
      expect(result.text).not.toContain("\n\n\n");
    });
  });
});

describe("comparison with other block elements (control group)", () => {
  it("paragraphs should have double newline separation", () => {
    const input = "paragraph 1\n\nparagraph 2";
    const result = markdownToIR(input);

    expect(result.text).toBe("paragraph 1\n\nparagraph 2");
    expect(result.text).not.toContain("\n\n\n");
  });

  it("list followed by paragraph should have double newline", () => {
    const input = "- item 1\n- item 2\n\nparagraph";
    const result = markdownToIR(input);

    // Lists already work correctly
    expect(result.text).toContain("• item 2\n\nparagraph");
    expect(result.text).not.toContain("\n\n\n");
  });

  it("heading followed by paragraph should have double newline", () => {
    const input = "# Heading\n\nparagraph";
    const result = markdownToIR(input);

    expect(result.text).toBe("Heading\n\nparagraph");
    expect(result.text).not.toContain("\n\n\n");
  });
});
