import { describe, it, expect } from "vitest";
import { validate } from "class-validator";
import { plainToInstance } from "class-transformer";
import { SearchQueryDto } from "./search-query.dto";

/**
 * Validation tests for SearchQueryDto
 *
 * Verifies that the full-text knowledge search endpoint
 * enforces input length limits to prevent abuse.
 */
describe("SearchQueryDto - Input Validation", () => {
  it("should pass validation with a valid query string", async () => {
    const dto = plainToInstance(SearchQueryDto, {
      q: "search term",
    });

    const errors = await validate(dto);
    expect(errors).toHaveLength(0);
  });

  it("should pass validation with a query at exactly 500 characters", async () => {
    const dto = plainToInstance(SearchQueryDto, {
      q: "a".repeat(500),
    });

    const errors = await validate(dto);
    expect(errors).toHaveLength(0);
  });

  it("should reject a query exceeding 500 characters", async () => {
    const dto = plainToInstance(SearchQueryDto, {
      q: "a".repeat(501),
    });

    const errors = await validate(dto);
    expect(errors.length).toBeGreaterThan(0);
    const qError = errors.find((e) => e.property === "q");
    expect(qError).toBeDefined();
    expect(qError!.constraints).toHaveProperty("maxLength");
    expect(qError!.constraints!.maxLength).toContain("500");
  });

  it("should reject a missing q field", async () => {
    const dto = plainToInstance(SearchQueryDto, {});

    const errors = await validate(dto);
    expect(errors.length).toBeGreaterThan(0);
    const qError = errors.find((e) => e.property === "q");
    expect(qError).toBeDefined();
  });

  it("should reject a non-string q field", async () => {
    const dto = plainToInstance(SearchQueryDto, {
      q: 12345,
    });

    const errors = await validate(dto);
    expect(errors.length).toBeGreaterThan(0);
    const qError = errors.find((e) => e.property === "q");
    expect(qError).toBeDefined();
  });

  it("should pass validation with optional fields included", async () => {
    const dto = plainToInstance(SearchQueryDto, {
      q: "search term",
      page: 1,
      limit: 10,
    });

    const errors = await validate(dto);
    expect(errors).toHaveLength(0);
  });

  it("should reject limit exceeding 100", async () => {
    const dto = plainToInstance(SearchQueryDto, {
      q: "search term",
      limit: 101,
    });

    const errors = await validate(dto);
    expect(errors.length).toBeGreaterThan(0);
    const limitError = errors.find((e) => e.property === "limit");
    expect(limitError).toBeDefined();
  });
});
