import { describe, it, expect, vi } from 'vitest';
import { type DuplicateCandidate, type IDuplicateDetector } from '../services/duplicate-detector';

/**
 * Contract-level tests for the duplicate detector.
 *
 * After TEC-2932 the detector no longer surfaces a `titleSimilarity` score —
 * hard duplicates are decided on the (sameAgent + addressMatch + radius)
 * combination instead. These tests pin the new candidate shape so refactors
 * can't silently re-introduce the old fuzzy heuristic.
 */
describe('IDuplicateDetector contract', () => {
  it('returns candidates carrying the new addressMatch / sameAgent flags', async () => {
    const mockCandidates: DuplicateCandidate[] = [
      {
        listingId: 'listing-1',
        propertyId: 'property-1',
        title: 'Bán nhà phố Quận 1',
        address: '123 Lê Lợi',
        district: 'Quận 1',
        distanceMeters: 30,
        addressMatch: true,
        sameAgent: true,
        propertyType: 'TOWNHOUSE',
      },
    ];

    const mockDetector: IDuplicateDetector = {
      findDuplicates: vi.fn().mockResolvedValue(mockCandidates),
    };

    const result = await mockDetector.findDuplicates({
      latitude: 10.7769,
      longitude: 106.7009,
      addressNormalized: '123 le loi phuong ben nghe quan 1 tp ho chi minh',
      agentId: 'agent-1',
      propertyType: 'TOWNHOUSE',
    });

    expect(result).toHaveLength(1);
    expect(result[0]!.addressMatch).toBe(true);
    expect(result[0]!.sameAgent).toBe(true);
    expect(result[0]!.distanceMeters).toBe(30);
    expect((result[0] as { titleSimilarity?: number }).titleSimilarity).toBeUndefined();
  });

  it('returns empty array when detector finds no candidates', async () => {
    const mockDetector: IDuplicateDetector = {
      findDuplicates: vi.fn().mockResolvedValue([]),
    };

    const result = await mockDetector.findDuplicates({
      latitude: 10.7769,
      longitude: 106.7009,
      addressNormalized: 'unique address',
      propertyType: 'APARTMENT',
    });

    expect(result).toHaveLength(0);
  });

  it('caller is expected to swallow detector errors (handler contract)', async () => {
    const mockDetector: IDuplicateDetector = {
      findDuplicates: vi.fn().mockRejectedValue(new Error('DB connection lost')),
    };

    let warnings: DuplicateCandidate[] = [];
    try {
      warnings = await mockDetector.findDuplicates({
        latitude: 10.7769,
        longitude: 106.7009,
        propertyType: 'VILLA',
      });
    } catch {
      warnings = [];
    }

    expect(warnings).toHaveLength(0);
  });
});
