import { buildBatchMassExampleText, buildBatchMassHeaderLine, buildBatchMassPreview, mergeMassRows } from './batch-mass-input.util';

describe('batch-mass-input.util', () => {
  it('parses rows separated by semicolon', () => {
    const preview = buildBatchMassPreview(
      '11999999999;8955000000000000001;Usuario 1;eSIM;PLANO A;ATIVO;EMPRESA A;CONTA A;2026-01-01;2027-01-01'
    );

    expect(preview.separator).toBe('SEMICOLON');
    expect(preview.recognizedRows).toBe(1);
    expect(preview.rows[0].data['linha']).toBe('11999999999');
    expect(preview.rows[0].data['chip']).toBe('8955000000000000001');
    expect(preview.rows[0].data['planoContrato']).toBe('PLANO A');
    expect(preview.rows[0].errors).toEqual([]);
  });

  it('parses rows separated by TAB', () => {
    const preview = buildBatchMassPreview(
      '11999999999\t8955000000000000001\tUsuario 1\teSIM\tPLANO A\tATIVO\tEMPRESA A\tCONTA A\t2026-01-01\t2027-01-01'
    );

    expect(preview.separator).toBe('TAB');
    expect(preview.recognizedRows).toBe(1);
    expect(preview.rows[0].data['usuario']).toBe('Usuario 1');
  });

  it('parses rows separated by pipe', () => {
    const preview = buildBatchMassPreview(
      '11999999999|8955000000000000001|Usuario 1|eSIM|PLANO A|ATIVO|EMPRESA A|CONTA A|2026-01-01|2027-01-01'
    );

    expect(preview.separator).toBe('PIPE');
    expect(preview.recognizedRows).toBe(1);
    expect(preview.rows[0].data['tipoDeChip']).toBe('eSIM');
  });

  it('ignores empty lines', () => {
    const preview = buildBatchMassPreview(
      '\n\n11999999999;8955;U1;eSIM;PLANO;ATIVO;EMPRESA;CONTA;2026-01-01;2027-01-01\n\n'
    );

    expect(preview.recognizedRows).toBe(1);
  });

  it('detects and uses header row when present', () => {
    const preview = buildBatchMassPreview(
      [
        'Linha;ICCID;Usuario;Tipo de Chip;Plano Contrato;Status;Empresa (Conta);Conta;Dt Efetivacao Servico;Dt Termino Fidelizacao',
        '11999999999;8955;U1;eSIM;PLANO;ATIVO;EMPRESA;CONTA;01/02/2026;01/02/2027'
      ].join('\n')
    );

    expect(preview.hasHeader).toBeTrue();
    expect(preview.recognizedRows).toBe(1);
    expect(preview.rows[0].data['dtEfetivacaoServico']).toBe('2026-02-01');
    expect(preview.rows[0].data['dtTerminoFidelizacao']).toBe('2027-02-01');
  });

  it('maps official header labels with parentheses (Chip (ICCID), Empresa (Conta))', () => {
    const preview = buildBatchMassPreview(
      [
        'Linha;Chip (ICCID);Usuario;Tipo de Chip;Plano Contrato;Status;Empresa (Conta);Conta;Dt. Efetivação Serviço;Dt. Término Fidelização',
        '11999999999;8955000000000000001;U1;eSIM;PLANO;ATIVO;EMPRESA;CONTA;2026-01-01;2027-01-01'
      ].join('\n')
    );

    expect(preview.hasHeader).toBeTrue();
    expect(preview.recognizedRows).toBe(1);
    expect(preview.rows[0].data['chip']).toBe('8955000000000000001');
    expect(preview.rows[0].data['contaEmpresa']).toBe('EMPRESA');
    expect(preview.rows[0].errors).toEqual([]);
  });

  it('fills missing columns with defaults when available', () => {
    const preview = buildBatchMassPreview('11999999999;8955', {
      defaults: {
        planoContrato: 'PLANO PADRAO',
        status: 'ATIVO',
        contaEmpresa: 'EMPRESA A',
        conta: 'CONTA A',
        dtEfetivacaoServico: '2026-01-01',
        dtTerminoFidelizacao: '2027-01-01'
      }
    });

    expect(preview.rows[0].data['planoContrato']).toBe('PLANO PADRAO');
    expect(preview.rows[0].data['status']).toBe('ATIVO');
    expect(preview.rows[0].errors).toEqual([]);
  });

  it('uses row value instead of default when both exist', () => {
    const preview = buildBatchMassPreview(
      '11999999999;8955;U1;eSIM;PLANO LINHA;SUSPENSO;EMPRESA LINHA;CONTA LINHA;2026-05-01;2027-05-01',
      {
        defaults: {
          planoContrato: 'PLANO PADRAO',
          status: 'ATIVO',
          contaEmpresa: 'EMPRESA PADRAO',
          conta: 'CONTA PADRAO',
          dtEfetivacaoServico: '2026-01-01',
          dtTerminoFidelizacao: '2027-01-01'
        }
      }
    );

    expect(preview.rows[0].data['planoContrato']).toBe('PLANO LINHA');
    expect(preview.rows[0].data['status']).toBe('SUSPENSO');
    expect(preview.rows[0].data['contaEmpresa']).toBe('EMPRESA LINHA');
  });

  it('marks row invalid when required fields are missing', () => {
    const preview = buildBatchMassPreview('11999999999;8955');

    expect(preview.invalidRows).toBe(1);
    expect(preview.rows[0].errors).toContain('Plano Contrato obrigatorio.');
    expect(preview.rows[0].errors).toContain('Status obrigatorio.');
    expect(preview.rows[0].errors).toContain('Empresa (Conta) obrigatoria.');
    expect(preview.rows[0].errors).toContain('Conta obrigatoria.');
    expect(preview.rows[0].errors).toContain('Dt. Efetivacao Servico obrigatoria.');
    expect(preview.rows[0].errors).toContain('Dt. Termino Fidelizacao obrigatoria.');
  });

  it('detects duplicate line numbers inside the batch', () => {
    const text = [
      '11999999999;8955;U1;eSIM;PLANO;ATIVO;EMPRESA;CONTA;2026-01-01;2027-01-01',
      '11 99999-9999;9999;U2;eSIM;PLANO;ATIVO;EMPRESA;CONTA;2026-01-01;2027-01-01'
    ].join('\n');

    const preview = buildBatchMassPreview(text);

    expect(preview.duplicateRows).toBe(2);
    expect(preview.rows[0].errors).toContain('Linha duplicada no lote.');
    expect(preview.rows[1].errors).toContain('Linha duplicada no lote.');
  });

  it('mergeMassRows keeps existing rows when mode is ADD', () => {
    const merged = mergeMassRows([{ linha: '1' }], [{ linha: '2' }, { linha: '3' }], 'ADD');

    expect(merged.map((x) => x.linha)).toEqual(['1', '2', '3']);
  });

  it('mergeMassRows replaces existing rows when mode is REPLACE', () => {
    const merged = mergeMassRows([{ linha: '1' }], [{ linha: '2' }, { linha: '3' }], 'REPLACE');

    expect(merged.map((x) => x.linha)).toEqual(['2', '3']);
  });

  it('builds header and example using selected separator', () => {
    const header = buildBatchMassHeaderLine('TAB');
    const example = buildBatchMassExampleText('PIPE', true);

    expect(header).toContain('\t');
    expect(example.split('\n')[0]).toContain('|');
    expect(example.split('\n').length).toBeGreaterThanOrEqual(3);
  });
});
