import React, { useEffect, useState } from 'react';
import {
    Alert,
    Button,
    Field,
    Form,
    SkeletonLoader,
} from '@theorchard/suite-components';
import { isEmpty, isEqual } from 'lodash-es';
import { Link, useHistory, useParams } from 'react-router-dom';
import {
    useCreateContractReserve,
    useUpdateContractReserve,
} from 'src/apollo/mutations/contract-reserve';
import { useContract } from 'src/apollo/queries/contract';
import { CONTRACT_TYPE_MAP } from 'src/apollo/type-constants/contract';
import { CONTRACT_TYPES } from 'src/constants';
import { useContractBreadcrumbs } from 'src/hooks/breadcrumbs/contract';
import { getContractDetail } from 'src/urls/frontend-royalties';
import { physicalReserveFormValidation } from 'src/utils/form-validations/physical-reserve-form-validation';
import { PageHeader } from '../shared/pageHeader';
import type {
    ContractReserveFormData,
    ContractReserveFormErrors,
} from 'src/types/contract-reserve';
import './styles.scss';

export const PhysicalReserveForm: React.FC = () => {
    const { contractId } = useParams<{ contractId: string }>();
    const [contractReserve, setContractReserve] = useState<any>({});
    const [validationErrors, setValidationErrors] =
        useState<ContractReserveFormErrors>({});
    const [errors, setErrors] = useState([]);
    const [formData, setFormData] = useState<ContractReserveFormData>({});
    const [contractType, setContractType] = useState<string | undefined>('');
    const addContractReserve = useCreateContractReserve(contractId);
    const updateContractReserve = useUpdateContractReserve(contractId);
    const history = useHistory();
    const breadcrumbs = useContractBreadcrumbs('Physical Reserves');

    const { data, loading: isContractLoading } = useContract(contractId);

    const onChange = (event: any) => {
        const { name, value } = event.target;
        if (isEmpty(errors)) setErrors([]);
        setFormData({
            ...formData,
            [name]: value,
        });
    };

    const submitHandler = () => {
        const validationResults = physicalReserveFormValidation(formData);
        setValidationErrors(validationResults);

        if (!isEmpty(validationResults)) return;

        const variables = {
            contractId,
            reserveRate: Number(formData.reserveRate),
            installmentsInMonths: Number(formData.installmentsInMonths),
            reserveReleaseOffsetInMonths: Number(
                formData.reserveReleaseOffsetInMonths
            ),
        };

        if (
            !isEmpty(contractReserve) &&
            !isEqual(variables, { ...formData, contractId })
        )
            updateContractReserve({ variables })
                .then(() => history.push(getContractDetail(contractId)))
                .catch(error => setErrors(error));
        else if (isEmpty(contractReserve))
            addContractReserve({ variables })
                .then(() => history.push(getContractDetail(contractId)))
                .catch(error => setErrors(error));
        else history.push(getContractDetail(contractId));
    };

    useEffect(() => {
        if (!isEmpty(data) && !isEmpty(data?.abacusContract?.reserve)) {
            const reserveData = data?.abacusContract?.reserve;
            setContractReserve(reserveData);
            setFormData({
                installmentsInMonths: reserveData?.installmentsInMonths,
                reserveRate: reserveData?.reserveRate,
                reserveReleaseOffsetInMonths:
                    reserveData?.reserveReleaseOffsetInMonths,
            });
        }

        if (!isEmpty(data) && !isEmpty(data?.abacusContract))
            setContractType(data?.abacusContract?.contractType);
    }, [data]);

    if (isContractLoading) return <SkeletonLoader />;

    if (
        contractType &&
        [CONTRACT_TYPES.NEIGHBOURING_RIGHTS].includes(contractType)
    )
        return (
            <div className="PhysicalReserveForm-noPhysicalReserve">
                {/* eslint-disable-next-line react/no-unescaped-entities */}
                Physical Reserves can not be added to "
                {/* eslint-disable-next-line react/no-unescaped-entities */}
                {CONTRACT_TYPE_MAP[contractType]}" contract.
            </div>
        );

    return (
        <div className="PhysicalReserveForm">
            <PageHeader title="Physical Reserves" breadcrumbs={breadcrumbs} />
            {errors.length > 0 && (
                <Alert
                    variant="error"
                    text={errors.map(err => (
                        <div key={err}>{err}</div>
                    ))}
                />
            )}
            <div className="container">
                <Form validated>
                    <div className="PhysicalReserveForm-item">
                        <Field
                            controlId="reserveRate"
                            labelText="Reserve Rate"
                            errorMessage={
                                validationErrors?.reserveRate || undefined
                            }
                            isRequired
                        >
                            <div
                                className="FormControlGroup"
                                data-testid="reserveRateFieldTestId"
                            >
                                <Form.Control
                                    name="reserveRate"
                                    onChange={onChange}
                                    type="number"
                                    value={formData.reserveRate || ''}
                                />
                                <span className="FormControlText">%</span>
                            </div>
                        </Field>
                    </div>
                    <div className="PhysicalReserveForm-item">
                        <Field
                            controlId="numberOfInstallments"
                            labelText="Number of Installments"
                            note="Reserves taken are divided evenly over the number of installments when released."
                            errorMessage={
                                validationErrors?.installmentsInMonths ||
                                undefined
                            }
                            isRequired
                        >
                            <div
                                className="FormControlGroup"
                                data-testid="installmentsInMonthsFieldTestId"
                            >
                                <Form.Control
                                    name="installmentsInMonths"
                                    onChange={onChange}
                                    type="number"
                                    value={formData.installmentsInMonths || ''}
                                />
                                <span className="FormControlText">Months</span>
                            </div>
                        </Field>
                    </div>
                    <div className="PhysicalReserveForm-item">
                        <Field
                            controlId="reserveReleaseOffsetInMonths"
                            labelText="First installment of Reserves Released After"
                            errorMessage={
                                validationErrors?.reserveReleaseOffsetInMonths ||
                                undefined
                            }
                            isRequired
                        >
                            <div
                                className="FormControlGroup"
                                data-testid="reserveReleaseFieldTestId"
                            >
                                <Form.Control
                                    name="reserveReleaseOffsetInMonths"
                                    onChange={onChange}
                                    type="number"
                                    value={
                                        formData.reserveReleaseOffsetInMonths ||
                                        ''
                                    }
                                />
                                <span className="FormControlText">Months</span>
                            </div>
                        </Field>
                    </div>
                </Form>
            </div>
            <div className="PhysicalReserveForm-btn-wrap">
                <Link to={getContractDetail(contractId)}>
                    <Button>Cancel</Button>
                </Link>
                <Button onClick={submitHandler} variant="primary">
                    Save
                </Button>
            </div>
        </div>
    );
};

export default PhysicalReserveForm;
