import React, { forwardRef } from 'react';
import * as RadixRadioGroup from '@radix-ui/react-radio-group';

import { theme, styled } from '../../stitches.config';

import { InputOptions } from '../../utility';
import { useValue } from '../../hooks';

import { Icon } from '../Icon';

const buildRadio = (valid: NonNullable<RadioItemProps['valid']>) => {
    let css = {};

    css = {
        ...css,
        cursor: 'pointer',
        '&[data-disabled]': {
            backgroundColor: theme.colors.base,
            borderColor: theme.colors['grey-4'],
            color: theme.colors['grey-4'],
            cursor: 'default',
            pointerEvents: 'none',
        },
    };

    if (valid) {
        css = {
            ...css,
            backgroundColor: theme.colors.base,
            borderColor: theme.colors['grey-2'],
            color: theme.colors['primary-1'],
            '&:hover': {
                color: theme.colors['primary-2'],
                backgroundColor: theme.colors['primary-5'],
                borderColor: theme.colors['primary-2'],
            },
        };
    } else {
        css = {
            ...css,
            backgroundColor: theme.colors.base,
            borderColor: theme.colors['error-1'],
            color: theme.colors['error-1'],
            '&:hover': {
                color: theme.colors['error-2'],
                backgroundColor: theme.colors['error-5'],
                borderColor: theme.colors['error-2'],
            },
        };
    }

    return {
        valid,
        css,
    };
};

const StyledLabel = styled('label', {
    cursor: 'pointer',
    display: 'flex',
    lineHeight: theme.space['5'],
    outline: 'none',
    position: 'relative',
    '&[data-disabled]': {
        cursor: 'default',
        pointerEvents: 'none',
    },
});

const StyledRadio = styled(RadixRadioGroup.Item, {
    borderRadius: theme.radii.full,
    borderWidth: theme.borderWidths.thick,
    height: theme.space['5'],
    width: theme.space['5'],
    display: 'block',
    flexGrow: '0',
    flexShrink: '0',
    outline: 'none',
    overflow: 'hidden',
    '&:focus': {
        outline: `2px solid ${theme.colors['primary-1']}`,
        outlineOffset: '2px',
    },
    variants: {
        valid: {
            true: {},
            false: {},
        },
    },
    compoundVariants: [buildRadio(true), buildRadio(false)],
    defaultVariants: {
        valid: true,
    },
});

const StyledIcon = styled(Icon, {
    display: 'block',
});

const StyledText = styled('div', {
    color: theme.colors['grey-1'],
    fontSize: theme.fontSizes.sm,
    margin: `0 0 0 ${theme.space['2']}`,
    overflow: 'hidden',
});

export interface RadioItemProps
    extends Omit<InputOptions<string>, 'onChange'>,
        Omit<
            React.ComponentPropsWithRef<'label'>,
            'value' | 'defaultValue' | 'defaultChecked' | 'onChange'
        > {}

// TODO: Need to figure out why @mdi/js isn't tree shaking
const mdiCircle =
    'M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2Z';

/**
 * RadioItem component
 */
export const RadioItem = forwardRef<HTMLLabelElement, RadioItemProps>(
    (props, ref): JSX.Element => {
        const {
            id,
            children,
            value,
            defaultValue,
            disabled,
            valid = true,
            ...otherProps
        } = props;

        // manage the internal value
        const [internalValue] = useValue({
            initialValue: '',
            value: value,
            defaultValue: defaultValue,
            onChange: () => null,
        });

        return (
            <StyledLabel
                ref={ref}
                data-disabled={disabled || undefined}
                {...otherProps}
            >
                <StyledRadio
                    id={id}
                    value={internalValue}
                    disabled={disabled}
                    valid={valid}
                    data-disabled={disabled || undefined}
                >
                    <RadixRadioGroup.Indicator>
                        <StyledIcon path={mdiCircle} size="1rem" />
                    </RadixRadioGroup.Indicator>
                </StyledRadio>
                <StyledText>{children}</StyledText>
            </StyledLabel>
        );
    },
);

RadioItem.displayName = 'RadioItem';
