import React from 'react';
import cx from 'classnames';
import { Form } from 'react-bootstrap';
import { Label } from '../label';
import { FieldMessage } from './fieldMessage';
import type { GlyphName16PX } from '@theorchard/suite-icons';

export const CLASS_NAME = 'FormField';

export interface Props {
    testId?: string;

    className?: string;

    style?: React.CSSProperties;

    /**
     * A string that will tie the label to the input, makes an id on the input, so should be unique
     */
    controlId: string;

    /**
     * The control fields you want to show the field wrapper around, usually input-like elements.
     */
    children: React.ReactNode;

    /**
     * The error message to show
     * @deprecated Use `message` prop instead.
     */
    errorMessage?: JSX.Element | string;

    /**
     * A note that is displayed at the lower part of the field.
     */
    note?: JSX.Element | string;

    /**
     * If the label should have a help icon, pass the text with this prop
     */
    helpText?: JSX.Element | string;

    /**
     * @deprecated No longer in use. Use `isOptional` to indicate optional fields.
     */
    isRequired?: boolean;

    /**
     * The label text
     */
    labelText: string;

    /**
     * Glyph icons, placed before label text
     */
    labelIcons?: GlyphName16PX[];

    /**
     * Appends text indicating the field is optional
     */
    isOptional?: boolean;

    /**
     * Do not hide tooltip when hovering over it.
     */
    helpHideOnHover?: boolean;

    /**
     * Type of message to show, can be 'error', 'warning' or 'loading'
     */
    message?: { type: 'error' | 'warning' | 'loading'; text: string };
}

/**
 * Field is a wrapper around a Form.Group and a Label.
 *
 * @type molecule
 * @status revised
 * @tags form-elements
 */
export const Field: React.FC<Props> = ({
    testId = CLASS_NAME,
    className,
    style,
    controlId,
    labelText,
    labelIcons,
    helpText,
    helpHideOnHover,
    isOptional,
    errorMessage, // Deprecated;
    isRequired,
    note,
    children,
    message: nMessage,
}) => {
    const message = nMessage || (errorMessage ? { type: 'error', text: errorMessage } : undefined);
    const withError = message?.type === 'error' || errorMessage !== undefined;
    const withOptional = isOptional || (isRequired !== undefined && isRequired === false);

    return (
        <div
            className={cx(CLASS_NAME, className, { 'with-error': withError })}
            style={style}
            data-testid={testId}
        >
            <Form.Group controlId={controlId}>
                <Label
                    className={`${CLASS_NAME}-label`}
                    text={labelText}
                    help={helpText ? { message: helpText, id: `help-${controlId}` } : undefined}
                    isOptional={withOptional}
                    helpHideOnHover={helpHideOnHover}
                    icons={labelIcons}
                />

                <div data-testid={`${CLASS_NAME}-control`} className={`${CLASS_NAME}-control`}>
                    {children}
                </div>

                <div className={`${CLASS_NAME}-note`}>{note}</div>

                {message && <FieldMessage {...message} />}
            </Form.Group>
        </div>
    );
};
