import React, { useMemo, useState } from 'react';
import PropTypes from 'prop-types';
import { useForm } from 'react-hook-form';
import merge from 'deepmerge';

import './styles/ProductQuestionForm.scss';
import withListener from '../withListener';
import { createNamespace } from '../../tools/namingTools';
import ProductCard from '../../atoms/product-card/ProductCard';
import { PRODUCT_DEFAULT_IMG } from '../../constants/images';
import { XSMALL } from '../../constants/sizes';
import Button from '../../atoms/button/Button';
import ButtonIcon from '../../atoms/button-icon/ButtonIcon';
import Input from '../../atoms/input/Input';
import Textarea from '../../atoms/textarea/Textarea';
import Icon from '../../atoms/icon/Icon';
import GridContainer from '../../atoms/grid-container/GridContainer';
import Preloader from '../../atoms/preloader/Preloader';
import { getCookieValue } from '../../tools/helpers';
import { addAlert, ALERT_QUESTION_ADD_SUCCESS, ALERT_QUESTION_ADD_ERROR } from '../../tools/alerts';

const n = createNamespace('ProductQuestionForm');

const REVIEW_MAX_LENGTH = 2048;

export const ProductQuestionFormComponent = ({
    data: {
        summary,
        questions
    }
}) => {
    const { actionEndpoint, i18n, questionFormReturnURL } = questions;
    const { handleSubmit, register, errors } = useForm();
    const [isSubmitting, setIsSubmitting] = useState(false);

    const onSubmit = values => {
        setIsSubmitting(true);
        const postURL = actionEndpoint;
        const valuesJSON = JSON.stringify(values);
        const XHR = new XMLHttpRequest();
        const success = [200, 201, 202, 204];
        // Define what happens on successful data submission
        XHR.addEventListener('load', () => {
            if (success.includes(XHR.status)) {
                addAlert(ALERT_QUESTION_ADD_SUCCESS);
                window.location.assign(questionFormReturnURL);
            } else {
                addAlert(ALERT_QUESTION_ADD_ERROR);
                window.location.assign(questionFormReturnURL);
            }
        });

        // Define what happens in case of error
        XHR.addEventListener('error', () => {
            addAlert(ALERT_QUESTION_ADD_ERROR);
            window.location.assign(questionFormReturnURL);
        });

        XHR.open('POST', postURL);
        XHR.setRequestHeader('Content-Type', 'application/json');
        XHR.setRequestHeader('X-XSRF-TOKEN', getCookieValue('XSRF-TOKEN'));
        XHR.send(valuesJSON);
    };

    const closeForm = () => {
        window.location.assign(questionFormReturnURL);
    };

    // memoize i18n defaults merge, as it does not change from state to state
    const i18nWithDefaults = useMemo(
        () => (
            merge(ProductQuestionFormComponent.defaultProps.data.questions.i18n, i18n)
        ),
        [i18n]
    );

    return (
        <section {...n('wrapper').withTestId().props}>
            <GridContainer {...n('container').props}>
                <div {...n('content').props}>
                    <h1 {...n('title').props}>{i18nWithDefaults.labels.askQuestion}</h1>
                    <div {...n('productCard').props} key="info">
                        <ProductCard
                            cardData={{ ...summary, size: XSMALL.value }}
                            settings={{ showRatings: false, productNameSize: XSMALL.value, descTextSize: XSMALL.value }}
                        />
                    </div>
                    <form onSubmit={handleSubmit(onSubmit)} {...n('wrapper').withTestId('form').props}>
                        <fieldset {...n('fieldset').props} key="question">
                            <legend {...n('legend').props}>{i18nWithDefaults.labels.writeQuestionLabel}</legend>
                            <div {...n('formGroup').props}>
                                <Input
                                    name="title"
                                    hiddenLabel
                                    error={errors.title && errors.title.message}
                                    label={i18nWithDefaults.labels.writeQuestionLabel}
                                    placeholder={i18nWithDefaults.labels.writeQuestionPlaceholder}
                                    aria-labelledby="headlineCaption"
                                    inputRef={register({
                                        required: {
                                            value: true,
                                            message: i18nWithDefaults.labels.writeQuestionValidation
                                        }
                                    })}
                                />
                            </div>
                            <p {...n('description').props} id="headlineCaption">{i18nWithDefaults.labels.writeQuestionDescription}</p>
                        </fieldset>
                        <fieldset {...n('fieldset').props} key="details">
                            <legend {...n('legend').props}>{i18nWithDefaults.labels.writeDetailsLabel}</legend>
                            <p {...n('description').props} id="detailsCaption">{i18nWithDefaults.labels.writeDetailsDescription}</p>
                            <div {...n('formGroup').props}>
                                <Textarea
                                    name="comment"
                                    hiddenLabel
                                    error={errors.comment && errors.comment.message}
                                    label={i18nWithDefaults.labels.writeDetailsLabel}
                                    placeholder={i18nWithDefaults.labels.writeDetailsPlaceholder}
                                    aria-labelledby="detailsCaption"
                                    inputRef={register({
                                        maxLength: {
                                            value: REVIEW_MAX_LENGTH,
                                            message: i18nWithDefaults.messages.error.textareaMaxLength
                                        }
                                    })}
                                />
                            </div>
                        </fieldset>
                        <div {...n('btnContainer').props} key="submit">
                            <ButtonIcon type="button" theme="primary" action="submit" disabled={isSubmitting} {...n('button').props}>
                                {i18nWithDefaults.labels.submitQuestion}
                            </ButtonIcon>
                            <Button buttonType="link" onClick={closeForm} {...n('button').props}>{i18nWithDefaults.labels.cancel}</Button>
                        </div>
                    </form>
                    <div {...n('closeButton').props}>
                        <Button buttonType="icon" onClick={closeForm}>
                            <span {...n('closeButtonText').props}>{i18nWithDefaults.labels.close}</span>
                            <Icon {...n('closeButtonIcon').props} type="close" />
                        </Button>
                    </div>
                </div>
            </GridContainer>
            <Preloader isLoading={isSubmitting} />
        </section>
    );
};

ProductQuestionFormComponent.schema = () => ({
    name: 'ProductQuestionForm',
    title: 'uieditor.sfbComponent.productQuestionForm.title',
    form: {},
    marketplaceData: {
        summary: 'application.summary',
        questions: 'application.questions'
    }
});

ProductQuestionFormComponent.propTypes = {
    data: PropTypes.shape({
        summary: PropTypes.shape({
            title: PropTypes.string,
            details: PropTypes.string,
            logoSrc: PropTypes.string,
            logoSrcset: PropTypes.shape({
                default: PropTypes.string,
                '2x': PropTypes.string,
                '1x': PropTypes.string
            })
        }),
        questions: PropTypes.shape({
            actionEndpoint: PropTypes.string.isRequired,
            questionFormReturnURL: PropTypes.string.isRequired,
            i18n: PropTypes.shape({
                labels: PropTypes.shape({
                    askQuestion: PropTypes.string,
                    writeQuestionLabel: PropTypes.string,
                    writeQuestionPlaceholder: PropTypes.string,
                    writeQuestionDescription: PropTypes.string,
                    writeQuestionValidation: PropTypes.string,
                    writeDetailsLabel: PropTypes.string,
                    writeDetailsPlaceholder: PropTypes.string,
                    writeDetailsDescription: PropTypes.string,
                    cancel: PropTypes.string,
                    close: PropTypes.string,
                    submitQuestion: PropTypes.string
                }),
                messages: PropTypes.shape({
                    success: PropTypes.shape({
                        postComment: PropTypes.string
                    }),
                    error: PropTypes.shape({
                        postEntry: PropTypes.string,
                        textareaMaxLength: PropTypes.string,
                        fieldRequired: PropTypes.string,
                        mustBeBetween: PropTypes.string
                    })
                })
            })
        })
    })
};

ProductQuestionFormComponent.defaultProps = {
    data: {
        summary: {
            title: null,
            details: null,
            logoSrc: PRODUCT_DEFAULT_IMG,
            logoSrcset: {
                default: null,
                '2x': null,
                '1x': null
            }
        },
        questions: {
            i18n: {
                labels: {
                    askQuestion: 'Ask a question',
                    writeQuestionLabel: 'Write a question',
                    writeQuestionPlaceholder: 'Type your question here',
                    writeQuestionDescription: 'Write a brief question summarizing what you most want to know about this product.',
                    writeQuestionValidation: 'Please write a question',
                    writeDetailsLabel: 'Write some details',
                    writeDetailsPlaceholder: 'Type some more information for your question',
                    writeDetailsDescription: 'Use this optional space to add some details or specifications regarding your question.',
                    cancel: 'Cancel',
                    close: 'Close the ask a question form',
                    submitQuestion: 'Submit Question'
                },
                messages: {
                    success: {
                        postEntry: 'Thank you for the review, it will be posted shortly'
                    },
                    error: {
                        postEntry: 'You must log in to write a review.',
                        textareaMaxLength: 'Must be at most 2048 characters',
                        fieldRequired: 'Required',
                        mustBeBetween: 'Must be between 1 and 5'
                    }
                }
            }
        }
    }
};

export default withListener(ProductQuestionFormComponent);
