import 'reflect-metadata';
import { CreateLeadDto } from '../dto/create-lead.dto';
import { ListLeadsDto } from '../dto/list-leads.dto';
import { UpdateLeadStatusDto } from '../dto/update-lead-status.dto';

describe('CreateLeadDto', () => {
  describe('validation metadata', () => {
    it('has name property metadata with Vietnamese description', () => {
      const metadata = Reflect.getMetadata(
        'swagger/apiModelProperties',
        CreateLeadDto.prototype,
        'name',
      );
      expect(metadata).toBeDefined();
      expect(metadata.description).toBe('Tên khách hàng tiềm năng');
      expect(metadata.example).toBe('Nguyễn Văn A');
    });

    it('has phone property metadata', () => {
      const metadata = Reflect.getMetadata(
        'swagger/apiModelProperties',
        CreateLeadDto.prototype,
        'phone',
      );
      expect(metadata).toBeDefined();
      expect(metadata.example).toBe('0901234567');
    });

    it('has email as optional property', () => {
      const metadata = Reflect.getMetadata(
        'swagger/apiModelProperties',
        CreateLeadDto.prototype,
        'email',
      );
      expect(metadata).toBeDefined();
      expect(metadata.required).toBeFalsy();
    });

    it('has score property with range description', () => {
      const metadata = Reflect.getMetadata(
        'swagger/apiModelProperties',
        CreateLeadDto.prototype,
        'score',
      );
      expect(metadata).toBeDefined();
      expect(metadata.description).toBe('Điểm lead (0-100)');
      expect(metadata.example).toBe(75);
    });
  });

  describe('property assignment', () => {
    it('can assign all required properties', () => {
      const dto = new CreateLeadDto();
      dto.name = 'Nguyễn Văn A';
      dto.phone = '0901234567';
      dto.source = 'website';

      expect(dto.name).toBe('Nguyễn Văn A');
      expect(dto.phone).toBe('0901234567');
      expect(dto.source).toBe('website');
    });

    it('can assign optional email and score', () => {
      const dto = new CreateLeadDto();
      dto.email = 'a@example.com';
      dto.score = 80;

      expect(dto.email).toBe('a@example.com');
      expect(dto.score).toBe(80);
    });

    it('optional fields default to undefined', () => {
      const dto = new CreateLeadDto();

      expect(dto.email).toBeUndefined();
      expect(dto.score).toBeUndefined();
      expect(dto.notes).toBeUndefined();
    });
  });
});

describe('ListLeadsDto', () => {
  describe('validation metadata', () => {
    it('has status property with enum values', () => {
      const metadata = Reflect.getMetadata(
        'swagger/apiModelProperties',
        ListLeadsDto.prototype,
        'status',
      );
      expect(metadata).toBeDefined();
      expect(metadata.enum).toEqual([
        'NEW',
        'CONTACTED',
        'QUALIFIED',
        'NEGOTIATING',
        'CONVERTED',
        'LOST',
      ]);
    });

    it('has page property with default 1', () => {
      const metadata = Reflect.getMetadata(
        'swagger/apiModelProperties',
        ListLeadsDto.prototype,
        'page',
      );
      expect(metadata).toBeDefined();
      expect(metadata.default).toBe(1);
    });

    it('has limit property with default 20', () => {
      const metadata = Reflect.getMetadata(
        'swagger/apiModelProperties',
        ListLeadsDto.prototype,
        'limit',
      );
      expect(metadata).toBeDefined();
      expect(metadata.default).toBe(20);
    });
  });

  describe('property assignment', () => {
    it('can assign all filter properties', () => {
      const dto = new ListLeadsDto();
      dto.status = 'NEW';
      dto.page = 2;
      dto.limit = 50;

      expect(dto.status).toBe('NEW');
      expect(dto.page).toBe(2);
      expect(dto.limit).toBe(50);
    });

    it('all properties default to undefined', () => {
      const dto = new ListLeadsDto();

      expect(dto.status).toBeUndefined();
      expect(dto.page).toBeUndefined();
      expect(dto.limit).toBeUndefined();
    });
  });
});

describe('UpdateLeadStatusDto', () => {
  describe('validation metadata', () => {
    it('has status property with enum values', () => {
      const metadata = Reflect.getMetadata(
        'swagger/apiModelProperties',
        UpdateLeadStatusDto.prototype,
        'status',
      );
      expect(metadata).toBeDefined();
      expect(metadata.enum).toEqual([
        'NEW',
        'CONTACTED',
        'QUALIFIED',
        'NEGOTIATING',
        'CONVERTED',
        'LOST',
      ]);
      expect(metadata.example).toBe('CONTACTED');
    });
  });

  describe('property assignment', () => {
    it('can assign status', () => {
      const dto = new UpdateLeadStatusDto();
      dto.status = 'CONTACTED';

      expect(dto.status).toBe('CONTACTED');
    });
  });
});
