import { describe, it, expect } from 'vitest';
import { GeoFilter } from '../value-objects/geo-filter.vo';
import { SearchFilter } from '../value-objects/search-filter.vo';

describe('Search Domain', () => {
  describe('SearchFilter', () => {
    it('creates filter with all properties', () => {
      const filter = SearchFilter.create({
        query: 'nhà phố quận 1',
        propertyType: 'TOWNHOUSE',
        transactionType: 'SALE',
        priceMin: 1_000_000_000,
        priceMax: 5_000_000_000,
        areaMin: 50,
        areaMax: 200,
        bedrooms: 3,
        district: 'Quận 1',
        city: 'Hồ Chí Minh',
        sortBy: 'price_asc',
        page: 2,
        perPage: 10,
      });

      expect(filter.query).toBe('nhà phố quận 1');
      expect(filter.propertyType).toBe('TOWNHOUSE');
      expect(filter.transactionType).toBe('SALE');
      expect(filter.priceMin).toBe(1_000_000_000);
      expect(filter.priceMax).toBe(5_000_000_000);
      expect(filter.areaMin).toBe(50);
      expect(filter.areaMax).toBe(200);
      expect(filter.bedrooms).toBe(3);
      expect(filter.district).toBe('Quận 1');
      expect(filter.city).toBe('Hồ Chí Minh');
      expect(filter.sortBy).toBe('price_asc');
      expect(filter.page).toBe(2);
      expect(filter.perPage).toBe(10);
    });

    it('applies default sortBy as relevance', () => {
      const filter = SearchFilter.create({});
      expect(filter.sortBy).toBe('relevance');
    });

    it('applies default page as 1', () => {
      const filter = SearchFilter.create({});
      expect(filter.page).toBe(1);
    });

    it('applies default perPage as 20', () => {
      const filter = SearchFilter.create({});
      expect(filter.perPage).toBe(20);
    });

    it('caps perPage at 100', () => {
      const filter = SearchFilter.create({ perPage: 500 });
      expect(filter.perPage).toBe(100);
    });

    it('returns undefined for unset optional properties', () => {
      const filter = SearchFilter.create({});
      expect(filter.query).toBeUndefined();
      expect(filter.propertyType).toBeUndefined();
      expect(filter.transactionType).toBeUndefined();
      expect(filter.priceMin).toBeUndefined();
      expect(filter.priceMax).toBeUndefined();
      expect(filter.areaMin).toBeUndefined();
      expect(filter.areaMax).toBeUndefined();
      expect(filter.bedrooms).toBeUndefined();
      expect(filter.district).toBeUndefined();
      expect(filter.city).toBeUndefined();
    });
  });

  describe('GeoFilter', () => {
    it('creates filter with all properties', () => {
      const filter = GeoFilter.create({
        lat: 10.7769,
        lng: 106.7009,
        radiusKm: 5,
        propertyType: 'APARTMENT',
        transactionType: 'RENT',
        priceMin: 5_000_000,
        priceMax: 20_000_000,
        sortBy: 'distance',
        page: 1,
        perPage: 15,
      });

      expect(filter.lat).toBe(10.7769);
      expect(filter.lng).toBe(106.7009);
      expect(filter.radiusKm).toBe(5);
      expect(filter.propertyType).toBe('APARTMENT');
      expect(filter.transactionType).toBe('RENT');
      expect(filter.priceMin).toBe(5_000_000);
      expect(filter.priceMax).toBe(20_000_000);
      expect(filter.sortBy).toBe('distance');
      expect(filter.page).toBe(1);
      expect(filter.perPage).toBe(15);
    });

    it('caps radiusKm at 100', () => {
      const filter = GeoFilter.create({ lat: 10.7, lng: 106.7, radiusKm: 200 });
      expect(filter.radiusKm).toBe(100);
    });

    it('applies default sortBy as distance', () => {
      const filter = GeoFilter.create({ lat: 10.7, lng: 106.7, radiusKm: 5 });
      expect(filter.sortBy).toBe('distance');
    });

    it('applies default page and perPage', () => {
      const filter = GeoFilter.create({ lat: 10.7, lng: 106.7, radiusKm: 5 });
      expect(filter.page).toBe(1);
      expect(filter.perPage).toBe(20);
    });

    it('caps perPage at 100', () => {
      const filter = GeoFilter.create({ lat: 10.7, lng: 106.7, radiusKm: 5, perPage: 300 });
      expect(filter.perPage).toBe(100);
    });
  });
});
