import { ComponentPropsWithRef, forwardRef, ForwardedRef } from 'react';
import * as RadixAccordion from '@radix-ui/react-accordion';

interface BaseAccordion<V>
    extends Omit<ComponentPropsWithRef<'div'>, 'onChange' | 'defaultValue'> {
    /** Value of the accordion */
    value: V;

    /** Callback that is triggered when the value changes */
    onChange?: (value: V) => void;

    /** Mark the accordion in a disabled/enabled state */
    disabled?: boolean;

    /** Mark the accordion as collapsible */
    collapsible?: boolean;
}

interface SingleAccordion extends BaseAccordion<string> {
    multiple: false;
}

interface MultipleAccordion extends BaseAccordion<string[]> {
    multiple: true;
}

export type AccordionProps = SingleAccordion | MultipleAccordion;

/**
 * Accordion component
 */
const _Accordion = (
    props: AccordionProps,
    ref: ForwardedRef<HTMLDivElement>,
): JSX.Element => {
    const {
        multiple = false,
        children,
        value,
        disabled,
        onChange,
        collapsible = true,
        ...otherProps
    } = props;

    //TODO: figure out why typescript doesn't like OR props
    if (!multiple) {
        return (
            <RadixAccordion.Root
                ref={ref}
                type="single"
                value={value as SingleAccordion['value']}
                disabled={disabled}
                onValueChange={
                    onChange as NonNullable<SingleAccordion['onChange']>
                }
                collapsible={collapsible}
                {...otherProps}
            >
                {children}
            </RadixAccordion.Root>
        );
    } else {
        return (
            <RadixAccordion.Root
                ref={ref}
                type="multiple"
                value={value as MultipleAccordion['value']}
                disabled={disabled}
                onValueChange={
                    onChange as NonNullable<MultipleAccordion['onChange']>
                }
                {...otherProps}
            >
                {children}
            </RadixAccordion.Root>
        );
    }
};

export const Accordion = forwardRef(_Accordion) as (
    props: AccordionProps & {
        ref?: ForwardedRef<HTMLDivElement>;
    },
) => ReturnType<typeof _Accordion>;
