import {
  validate,
  IsNotEmpty,
  IsOptional,
  IsString,
} from 'class-validator';
import { IsTin, normalizeTin } from './is-tin.validator';

class Required {
  @IsString()
  @IsNotEmpty()
  @IsTin({ message: 'TIN must be exactly 10 digits' })
  tin!: string;
}

class Optional {
  @IsOptional()
  @IsString()
  @IsTin({ message: 'TIN must be exactly 10 digits' })
  tin?: string;
}

async function errs(cls: any, tin: any) {
  const o = new cls();
  o.tin = tin;
  return (await validate(o)).length;
}

describe('IsTin', () => {
  it('accepts a real 10-digit TIN', async () => {
    expect(await errs(Required, '0012345678')).toBe(0);
  });

  it.each([
    ['letters', 'ABCDEFGHIJ'],
    ['symbols', '!!!!!!!!!!'],
    ['too short', '123'],
    ['too long', '12345678901'],
    ['draft TIN', 'D123456789'],
    ['spaced', '012 345678'],
  ])('rejects %s', async (_label, value) => {
    expect(await errs(Required, value)).toBeGreaterThan(0);
  });

  it('rejects empty on the required DTO but allows omission on the optional one', async () => {
    expect(await errs(Required, '')).toBeGreaterThan(0);
    expect(await errs(Optional, undefined)).toBe(0);
  });

  it('normalizes messy input', () => {
    expect(normalizeTin(' 001-234-5678 ')).toBe('0012345678');
    expect(normalizeTin('')).toBe('');
  });
});
