import { plainToInstance } from 'class-transformer';
import { validate } from 'class-validator';
import { describe, it, expect } from 'vitest';
import { SearchListingsDto } from '../dto/search-listings.dto';

describe('SearchListingsDto', () => {
  it('should pass validation with no filters (all optional)', async () => {
    const dto = plainToInstance(SearchListingsDto, {});

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

  it('should pass validation with valid status and filters', async () => {
    const dto = plainToInstance(SearchListingsDto, {
      status: 'ACTIVE',
      transactionType: 'SALE',
      propertyType: 'APARTMENT',
      city: 'Hồ Chí Minh',
      district: 'Quận 1',
      page: 1,
      limit: 20,
    });

    const errors = await validate(dto);
    expect(errors).toHaveLength(0);
    expect(dto.status).toBe('ACTIVE');
    expect(dto.transactionType).toBe('SALE');
  });

  it('should fail validation with invalid status enum', async () => {
    const dto = plainToInstance(SearchListingsDto, {
      status: 'INVALID_STATUS',
    });

    const errors = await validate(dto);
    expect(errors.length).toBeGreaterThan(0);
    const statusError = errors.find((e) => e.property === 'status');
    expect(statusError).toBeDefined();
  });

  it('should fail validation when limit exceeds 100', async () => {
    const dto = plainToInstance(SearchListingsDto, {
      limit: 200,
    });

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

  it('should fail validation when page is less than 1', async () => {
    const dto = plainToInstance(SearchListingsDto, {
      page: 0,
    });

    const errors = await validate(dto);
    expect(errors.length).toBeGreaterThan(0);
    const pageError = errors.find((e) => e.property === 'page');
    expect(pageError).toBeDefined();
  });

  it('should pass validation with area and bedroom filters', async () => {
    const dto = plainToInstance(SearchListingsDto, {
      minArea: 50,
      maxArea: 200,
      bedrooms: 2,
    });

    const errors = await validate(dto);
    expect(errors).toHaveLength(0);
    expect(dto.minArea).toBe(50);
    expect(dto.maxArea).toBe(200);
    expect(dto.bedrooms).toBe(2);
  });

  it('should accept order=desc alongside sortBy=publishedAt (TEC-3088)', async () => {
    const dto = plainToInstance(SearchListingsDto, {
      page: 1,
      limit: 50,
      status: 'ACTIVE',
      sortBy: 'publishedAt',
      order: 'desc',
    });

    const errors = await validate(dto);
    expect(errors).toHaveLength(0);
    expect(dto.sortBy).toBe('publishedAt');
    expect(dto.order).toBe('desc');
  });

  it('should accept order=asc', async () => {
    const dto = plainToInstance(SearchListingsDto, { order: 'asc' });
    const errors = await validate(dto);
    expect(errors).toHaveLength(0);
    expect(dto.order).toBe('asc');
  });

  it('should reject invalid order value', async () => {
    const dto = plainToInstance(SearchListingsDto, { order: 'sideways' });
    const errors = await validate(dto);
    expect(errors.length).toBeGreaterThan(0);
    const orderError = errors.find((e) => e.property === 'order');
    expect(orderError).toBeDefined();
  });
});
