/**
 * This file is part of the NocoBase (R) project.
 * Copyright (c) 2020-2024 NocoBase Co., Ltd.
 * Authors: NocoBase Team.
 *
 * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
 * For more information, please refer to: https://www.nocobase.com/agreement.
 */

import { fireEvent, render, screen } from '@nocobase/test/client';
import React from 'react';
import { formatNumberWithSeparator, formatUnitConversion, scientificNotation, formatNumber } from '../ReadPretty';
import App2 from '../demos/addonBefore&addonAfter';
import App3 from '../demos/highPrecisionDecimals';
import App1 from '../demos/inputNumber';

describe('InputNumber', () => {
  it('should display the title', () => {
    render(<App1 />);

    expect(screen.getByText('Editable').innerHTML).toBe('Editable');
    expect(screen.getByText('Read pretty').innerHTML).toBe('Read pretty');
  });

  it('should display the value of user input', async () => {
    const { container } = render(<App1 />);

    const input = container.querySelector('input') as HTMLInputElement;
    fireEvent.change(input, { target: { value: 1 } });
    expect(input.value).toBe('1');
    // @ts-ignore
    expect(screen.getByText('1')).toBeInTheDocument();

    // empty value
    fireEvent.change(input, { target: { value: '' } });
    expect(input.value).toBe('');
    expect(screen.queryByText('NaN')).toBeNull();
  });
});

describe('InputNumber: addonBefore/addonAfter', () => {
  it('should display the title', () => {
    render(<App2 />);

    expect(screen.getByText('Editable').innerHTML).toBe('Editable');
    expect(screen.getByText('Read pretty').innerHTML).toBe('Read pretty');
  });

  it('should display the value of user input', async () => {
    const { container } = render(<App2 />);

    const input = container.querySelector('input') as HTMLInputElement;
    fireEvent.change(input, { target: { value: 1 } });
    expect(input.value).toBe('1');
    // @ts-ignore
    expect(screen.getByText('¥')).toBeInTheDocument();

    // empty value
    fireEvent.change(input, { target: { value: '' } });
    expect(input.value).toBe('');
    expect(screen.queryByText('NaN')).toBeNull();
  });
});

describe('InputNumber: High precision decimals', () => {
  it('should display the title', () => {
    render(<App3 />);

    expect(screen.getByText('Editable').innerHTML).toBe('Editable');
    expect(screen.getByText('Read pretty').innerHTML).toBe('Read pretty');
  });

  it('should display the value of user input', async () => {
    const { container } = render(<App3 />);

    const input = container.querySelector('input') as HTMLInputElement;
    fireEvent.change(input, { target: { value: 1 } });
    expect(input.value).toBe('1.00');
    // @ts-ignore
    expect(screen.getByText('1.00')).toBeInTheDocument();

    // empty value
    fireEvent.change(input, { target: { value: '' } });
    expect(input.value).toBe('');
    expect(screen.queryByText('NaN')).toBeNull();
  });
});

describe('ReadPretty:formatNumberWithSeparator', () => {
  // Test case 1: Format a number with default format '0,0.00'
  test('Format number with default separator', () => {
    const formatted = formatNumberWithSeparator(1234567.89);
    expect(formatted).toBe('1234567.9');
  });

  // Test case 2: Format a number with custom format '0.00'
  test('Format number with custom separator', () => {
    const formatted = formatNumberWithSeparator(1234567.89, '0,0.00', 1);
    expect(formatted).toBe('1,234,567.9');
  });

  test('Format number with custom 0 0,00 separator', () => {
    const formatted = formatNumberWithSeparator(1234567.89, '0 0,00', 1);
    expect(formatted).toBe('1 234 567.9');
  });
  test('Format number with custom 0.00 separator', () => {
    const formatted = formatNumberWithSeparator(1234567.89, '0.00', 1);
    expect(formatted).toBe('1234567.9');
  });
});
describe('ReadPretty:formatUnitConversion', () => {
  // Test case 1: Multiply a value by 2
  test('Multiply value by 2', () => {
    const result = formatUnitConversion(10, '*', 2);
    expect(result).toBe(20);
  });
  // Test case 2: Divide a value by 0 (error case)
  test('Divide value by zero', () => {
    const result = formatUnitConversion(10, '/', 0);
    expect(result).toBe(10);
  });

  test('0.1*0.2', () => {
    const result = formatUnitConversion(0.1, '*', 0.2);
    expect(result).toBe(0.02);
  });
});

describe('ReadPretty:MAX_SAFE_INTEGER', () => {
  test('value > Number.MAX_SAFE_INTEGER || value < Number.MIN_SAFE_INTEGER', () => {
    const result = formatNumber({
      value: '1691195350092210177',
      formatStyle: 'normal',
      step: 1,
    });
    expect(result).toBe('1,691,195,350,092,210,177');
  });
  test('normal value', () => {
    const result = formatNumber({ value: 3, formatStyle: 'normal', step: 1 });
    expect(result).toBe('3');
  });
});

describe('ReadPretty:scientificNotation', () => {
  // Test case 1: Format a number into scientific notation with 2 decimal places
  test('Format number into scientific notation', () => {
    const formatted = scientificNotation(1234567.89, 2);
    expect(formatted).toBe('1.23×10<sup>6</sup>');
  });

  // Test case 2: Format a number into scientific notation with custom separator '.'
  test('Format number into scientific notation with custom separator', () => {
    const formatted = scientificNotation(1234567.89, 2, '.');
    expect(formatted).toBe('1.23×10<sup>6</sup>');
  });
});
