import React from 'react';
import { render, fireEvent } from '@testing-library/react';
import { testComponent } from 'lib/test-utils/common';
import {
    ExpandableContent,
    ExpandableContentProps,
    CLASSNAME,
    LABEL_WRAPPER_CLASSNAME,
    CONTENT_CLASSNAME,
} from '../expandableContent';
import { t } from '../i18n';

describe('<ExpandableContent>', () => {
    const content = 'Test content';
    const defaultProps: ExpandableContentProps = { children: content };

    const renderComponent = (props: ExpandableContentProps = defaultProps) =>
        render(<ExpandableContent {...props} />);

    testComponent(ExpandableContent);

    test('applies style', () => {
        const { getByTestId } = renderComponent({ ...defaultProps, style: { marginTop: 10 } });
        expect(getByTestId(CLASSNAME)).toHaveStyle({ marginTop: '10px' });
    });

    test('renders with default props', () => {
        const { getByText, queryByText } = renderComponent();

        expect(getByText(t('more_info'))).toBeInTheDocument();
        const contentElement = queryByText(content);
        expect(contentElement).toBeInTheDocument();
        expect(contentElement).toHaveAttribute('aria-hidden', 'true');
    });

    test('toggles content visibility on click', async () => {
        const { getByText, getByTestId, queryByTestId } = renderComponent();
        const toggle = getByTestId(CLASSNAME).querySelector(`.${LABEL_WRAPPER_CLASSNAME}`);
        const contentElement = getByTestId(CLASSNAME).querySelector(`.${CONTENT_CLASSNAME}`);

        expect(getByTestId('DoubleChevronDownGlyphIcon')).toBeInTheDocument();
        expect(queryByTestId('DoubleChevronUpGlyphIcon')).not.toBeInTheDocument();

        if (toggle) fireEvent.click(toggle);

        expect(contentElement).toHaveAttribute('aria-hidden', 'false');
        expect(getByText(t('more_info'))).toBeInTheDocument();
        expect(contentElement).toHaveTextContent(content);
        expect(getByTestId('DoubleChevronUpGlyphIcon')).toBeInTheDocument();
        expect(queryByTestId('DoubleChevronDownGlyphIcon')).not.toBeInTheDocument();

        if (toggle) fireEvent.click(toggle);

        expect(contentElement).toHaveAttribute('aria-hidden', 'true');
        expect(getByText(t('more_info'))).toBeInTheDocument();
        expect(getByTestId('DoubleChevronDownGlyphIcon')).toBeInTheDocument();
        expect(queryByTestId('DoubleChevronUpGlyphIcon')).not.toBeInTheDocument();
    });

    test('renders custom className', () => {
        const className = 'customClass';
        const { getByTestId } = renderComponent({ ...defaultProps, className });

        expect(getByTestId(CLASSNAME)).toHaveClass(className);
    });

    test('renders if only `collapseLabel` is provided', () => {
        const expandLabel = 'More info custom';
        const { getByText, queryByText, getByTestId } = renderComponent({
            ...defaultProps,
            expandLabel,
        });
        const toggle = getByTestId(CLASSNAME).querySelector(`.${LABEL_WRAPPER_CLASSNAME}`);

        expect(getByText(expandLabel)).toBeInTheDocument();
        expect(queryByText(t('more_info'))).not.toBeInTheDocument();

        if (toggle) fireEvent.click(toggle);

        expect(queryByText(t('more_info'))).not.toBeInTheDocument();
        expect(getByText(expandLabel)).toBeInTheDocument();
    });

    test('renders custom labels', () => {
        const expandLabel = 'Expand';
        const collapseLabel = 'Collapse';
        const { getByText, queryByText, getByTestId } = renderComponent({
            ...defaultProps,
            expandLabel,
            collapseLabel,
        });
        const toggle = getByTestId(CLASSNAME).querySelector(`.${LABEL_WRAPPER_CLASSNAME}`);

        expect(getByText(expandLabel)).toBeInTheDocument();
        expect(queryByText(collapseLabel)).not.toBeInTheDocument();

        if (toggle) fireEvent.click(toggle);

        expect(queryByText(expandLabel)).not.toBeInTheDocument();
        expect(getByText(collapseLabel)).toBeInTheDocument();
    });

    test('renders with `defaultExpanded`', () => {
        const { getByTestId } = renderComponent({ ...defaultProps, defaultExpanded: true });
        const contentElement = getByTestId(CLASSNAME).querySelector(`.${CONTENT_CLASSNAME}`);

        expect(contentElement).toHaveAttribute('aria-hidden', 'false');
    });

    test('triggers `onClick` from props', () => {
        const onClick = vi.fn();

        const { getByTestId } = renderComponent({ ...defaultProps, onClick });
        const toggle = getByTestId(CLASSNAME).querySelector(`.${LABEL_WRAPPER_CLASSNAME}`);

        if (toggle) fireEvent.click(toggle);

        expect(onClick).toHaveBeenCalledWith(true);
    });

    test('triggers `onToggle` from props', () => {
        const onToggle = vi.fn();

        const { getByTestId } = renderComponent({ ...defaultProps, onToggle });
        const toggle = getByTestId(CLASSNAME).querySelector(`.${LABEL_WRAPPER_CLASSNAME}`);

        if (toggle) fireEvent.click(toggle);

        expect(onToggle).toHaveBeenCalledWith(true);
    });

    test('prioritizes `onToggle` over `onClick` when both are provided', () => {
        const onClick = vi.fn();
        const onToggle = vi.fn();

        const { getByTestId } = renderComponent({ ...defaultProps, onClick, onToggle });
        const toggle = getByTestId(CLASSNAME).querySelector(`.${LABEL_WRAPPER_CLASSNAME}`);

        if (toggle) fireEvent.click(toggle);

        expect(onToggle).toHaveBeenCalledWith(true);
        expect(onClick).not.toHaveBeenCalled();
    });

    test('works in controlled mode with `expanded` prop', async () => {
        const onToggle = vi.fn();
        const { getByTestId, rerender } = render(
            <ExpandableContent expanded={false} onToggle={onToggle}>
                {content}
            </ExpandableContent>
        );

        const contentElement = getByTestId(CLASSNAME).querySelector(`.${CONTENT_CLASSNAME}`);
        const toggle = getByTestId(CLASSNAME).querySelector(`.${LABEL_WRAPPER_CLASSNAME}`);

        expect(contentElement).toHaveAttribute('aria-hidden', 'true');

        if (toggle) fireEvent.click(toggle);

        expect(onToggle).toHaveBeenCalledWith(true);

        rerender(
            <ExpandableContent expanded={true} onToggle={onToggle}>
                {content}
            </ExpandableContent>
        );

        expect(contentElement).toHaveAttribute('aria-hidden', 'false');
    });

    test('controlled mode ignores internal state changes', () => {
        const onToggle = vi.fn();
        const { getByTestId } = render(
            <ExpandableContent expanded={false} onToggle={onToggle}>
                {content}
            </ExpandableContent>
        );

        const contentElement = getByTestId(CLASSNAME).querySelector(`.${CONTENT_CLASSNAME}`);
        const toggle = getByTestId(CLASSNAME).querySelector(`.${LABEL_WRAPPER_CLASSNAME}`);

        expect(contentElement).toHaveAttribute('aria-hidden', 'true');

        if (toggle) fireEvent.click(toggle);

        expect(onToggle).toHaveBeenCalledWith(true);
        expect(contentElement).toHaveAttribute('aria-hidden', 'true');
    });
});
