import { render } from '@testing-library/react';
import dayjs from 'dayjs';
import localizedFormat from 'dayjs/plugin/localizedFormat';
import timezone from 'dayjs/plugin/timezone';
import utc from 'dayjs/plugin/utc';
import TimezonedDatetime, { format, signed } from '../timezoned-datetime';
import type { TimezonedDatetimeProps } from '../timezoned-datetime';

dayjs.extend(utc);
dayjs.extend(timezone);
dayjs.extend(localizedFormat);

const date = dayjs('2023-02-18T17:59:21Z').toDate();

describe('format', () => {
    const placeholder = '--';
    const iana = 'America/New_York';

    test('renders formatted datetime', () =>
        expect(format({ date, iana, placeholder })).toEqual(
            dayjs.utc(date).tz(iana).format('D MMM YYYY hh:mma')
        ));

    describe('date is undefined', () => {
        test('returns placeholder', () =>
            expect(format({ iana, placeholder })).toEqual(placeholder));
    });

    describe('iana is undefined', () => {
        test('returns placeholder', () =>
            expect(format({ date, placeholder })).toEqual(placeholder));
    });
});

describe('signed', () => {
    describe('< 0', () => {
        const number = -1;
        test('returns string representation with negative prefix', () => {
            const result = signed(number);
            expect(result).toEqual(number.toString());
            expect(result[0]).toEqual('-');
        });
    });

    describe('=== 0', () => {
        test('returns "0"', () => expect(signed(0)).toEqual('0'));
    });

    describe('> 0', () => {
        const number = 300;
        test('returns string representation with positive prefix', () =>
            expect(signed(number)).toEqual(`+${number.toString()}`));
    });
});

describe('<TimezonedDatetime>', () => {
    const timezone = {
        offset: -5,
        abbreviation: 'ET',
        iana: 'America/New_York',
    };
    const { offset, abbreviation, iana } = timezone;
    const defaultProps: TimezonedDatetimeProps = {
        date,
        timezone,
    };

    const renderWrapper = (props: Partial<TimezonedDatetimeProps> = {}) =>
        render(<TimezonedDatetime {...defaultProps} {...props} />);

    describe('.TimezonedDatetime-timezone', () => {
        test('contains abberviation with UTC and signed offset', () => {
            const { container } = renderWrapper();
            const [timezoneEl] = container.getElementsByClassName(
                'TimezonedDatetime-timezone'
            );
            expect(timezoneEl).toHaveTextContent(
                `${abbreviation} (UTC ${signed(offset)}):`
            );
        });
    });

    describe('.TimezonedDatetime-formatted', () => {
        test('contains result of format function', () => {
            const { container } = renderWrapper();
            const [formattedEl] = container.getElementsByClassName(
                'TimezonedDatetime-formatted'
            );
            expect(formattedEl).toHaveTextContent(format({ date, iana }));
        });
    });
});
