import React, { useState, useRef, useLayoutEffect } from 'react';
import cx from 'classnames';
import { createPortal } from 'react-dom';
import { SidebarHeader, SidebarContent } from './components';
import { CLASSNAME, PORTAL_CLASSNAME } from './constants';

export interface Props {
    portalElement?: Element | null;
    isOpen: boolean;
    onRequestClose: () => void;
    title?: string;
    children: React.ReactNode;
    className?: string;
    testId?: string;
    // Whether to render content when sidebar is closed
    unmountOnClose?: boolean;
}

/**
 * Sidebars are collapsible elements designed to present additional information to the original content of a page. They remain hidden by default to maximise available space. They differ from sidecars as per their nature: they are inline elements that push content, they aren’t overlays.
 *
 * @type template
 * @status live
 * @tags layout-structure
 *
 */
export const Sidebar = ({
    portalElement,
    isOpen,
    onRequestClose,
    title,
    children,
    className,
    testId = CLASSNAME,
    unmountOnClose = true,
}: Props) => {
    const sidebarRef = useRef<HTMLDivElement>(null);
    const [transitioning, setTransitioning] = useState(false);

    // Track transitions to ensure content is rendered while sidebar is closing
    useLayoutEffect(() => {
        if (isOpen) return;
        setTransitioning(true);

        const controller = new AbortController();
        sidebarRef.current?.addEventListener('transitionend', () => setTransitioning(false), {
            signal: controller.signal,
        });

        return () => {
            controller.abort();
        };
    }, [isOpen]);

    const container = portalElement || document.getElementsByClassName(PORTAL_CLASSNAME).item(0);
    if (!container) {
        console.error(`Sidebar: Unable to find portal element`);
        return null;
    }
    return createPortal(
        <div className={`${CLASSNAME}-container`} ref={sidebarRef}>
            <div className={cx(CLASSNAME, className, { open: isOpen })} data-testid={testId}>
                {(!unmountOnClose || isOpen || transitioning) && (
                    <>
                        <SidebarHeader onRequestClose={onRequestClose} title={title} />
                        <SidebarContent>{children}</SidebarContent>
                    </>
                )}
            </div>
        </div>,
        container
    );
};
