/**
 * TextValidationPipe Tests
 *
 * Issue #398: Validates text input for TTS synthesis.
 * Tests cover text length, empty text, whitespace, and configurable limits.
 */

import { describe, it, expect, beforeEach } from "vitest";
import { BadRequestException } from "@nestjs/common";
import { TextValidationPipe } from "./text-validation.pipe";

describe("TextValidationPipe", () => {
  // ==========================================
  // Default config (4096 max length)
  // ==========================================
  describe("with default config", () => {
    let pipe: TextValidationPipe;

    beforeEach(() => {
      pipe = new TextValidationPipe();
    });

    // ==========================================
    // Valid text
    // ==========================================
    describe("valid text", () => {
      it("should accept normal text", () => {
        const text = "Hello, world!";
        expect(pipe.transform(text)).toBe(text);
      });

      it("should accept text at exactly the max length", () => {
        const text = "a".repeat(4096);
        expect(pipe.transform(text)).toBe(text);
      });

      it("should accept single character text", () => {
        expect(pipe.transform("a")).toBe("a");
      });

      it("should accept text with unicode characters", () => {
        const text = "Hello, world! 你好世界";
        expect(pipe.transform(text)).toBe(text);
      });

      it("should accept multi-line text", () => {
        const text = "Line one.\nLine two.\nLine three.";
        expect(pipe.transform(text)).toBe(text);
      });
    });

    // ==========================================
    // Text length validation
    // ==========================================
    describe("text length validation", () => {
      it("should reject text exceeding max length", () => {
        const text = "a".repeat(4097);
        expect(() => pipe.transform(text)).toThrow(BadRequestException);
        expect(() => pipe.transform(text)).toThrow(/exceeds maximum/);
      });

      it("should include length details in error message", () => {
        const text = "a".repeat(5000);
        try {
          pipe.transform(text);
          expect.fail("Expected BadRequestException");
        } catch (error) {
          expect(error).toBeInstanceOf(BadRequestException);
          const response = (error as BadRequestException).getResponse();
          const message =
            typeof response === "string" ? response : (response as Record<string, unknown>).message;
          expect(message).toContain("5000");
          expect(message).toContain("4096");
        }
      });
    });

    // ==========================================
    // Empty text validation
    // ==========================================
    describe("empty text validation", () => {
      it("should reject empty string", () => {
        expect(() => pipe.transform("")).toThrow(BadRequestException);
        expect(() => pipe.transform("")).toThrow(/Text cannot be empty/);
      });

      it("should reject whitespace-only string", () => {
        expect(() => pipe.transform("   ")).toThrow(BadRequestException);
        expect(() => pipe.transform("   ")).toThrow(/Text cannot be empty/);
      });

      it("should reject tabs and newlines only", () => {
        expect(() => pipe.transform("\t\n\r")).toThrow(BadRequestException);
      });

      it("should reject null", () => {
        expect(() => pipe.transform(null as unknown as string)).toThrow(BadRequestException);
      });

      it("should reject undefined", () => {
        expect(() => pipe.transform(undefined as unknown as string)).toThrow(BadRequestException);
      });
    });

    // ==========================================
    // Text with leading/trailing whitespace
    // ==========================================
    describe("whitespace handling", () => {
      it("should accept text with leading/trailing whitespace (preserves it)", () => {
        const text = "  Hello, world!  ";
        expect(pipe.transform(text)).toBe(text);
      });
    });
  });

  // ==========================================
  // Custom config
  // ==========================================
  describe("with custom config", () => {
    it("should use custom max text length", () => {
      const pipe = new TextValidationPipe({ maxTextLength: 100 });

      const shortText = "Hello";
      expect(pipe.transform(shortText)).toBe(shortText);

      const longText = "a".repeat(101);
      expect(() => pipe.transform(longText)).toThrow(BadRequestException);
    });

    it("should accept text at exact custom limit", () => {
      const pipe = new TextValidationPipe({ maxTextLength: 50 });
      const text = "a".repeat(50);
      expect(pipe.transform(text)).toBe(text);
    });
  });
});
