import React, { useContext, useEffect, useState } from 'react';
import { Form, Container, Row, Col } from '@theorchard/suite-components';
import { isEmpty } from 'lodash-es';
import { useParams } from 'react-router-dom';
import { useContractAttachments } from 'src/apollo/queries/contract';
import LabelMultiSelect from 'src/components/shared/label-multiselect';
import LabelSelect from 'src/components/shared/label-select';
import ProductMultiSelect from 'src/components/shared/product-multiselect';
import TrackMultiSelect from 'src/components/shared/track-multiselect';
import {
    CONTRACT_TERM_NAME_CHAR_LIMIT,
    DISTRO_CONTRACT_TERM_TYPES,
    SET_ATTACHMENTS_RELATIONS,
    SET_CONTRACT_TERM,
    SET_CONTRACT_TERM_ATTACHMENTS,
    SET_DEFAULT_CONDITION,
    SET_ERRORS,
} from 'src/constants';
import { ContractTermContext } from 'src/contexts/contract-term-context';
import { ContractTermsDistroConditionsList } from './contract-terms-distro-conditions-list';
import type { GetContractWithAttachmentsQuery } from 'src/apollo/queries/contract/__generated__/get-contract-attachments';

type AbacusContract = NonNullable<
    GetContractWithAttachmentsQuery['abacusContract']
>;
type ContractTerms =
    NonNullable<AbacusContract['contractTerms']> extends (infer T)[] ? T : null;

export const ContractTermsDistroForm: React.FC = () => {
    const { contractId, contractTermId, termType } = useParams<{
        contractId: string;
        contractTermId: string;
        termType: string;
    }>();

    const { state, dispatch } = useContext(ContractTermContext);
    const { data: contract } = useContractAttachments(contractId);
    const [accountId, setAccountId] = useState<string>('');
    const [contractTerms, setContractTerms] = useState<ContractTerms[]>([]);
    const setErrors = (attachmentsValidError: any) =>
        dispatch({ type: SET_ERRORS, attachmentsValidError, error: [] });

    useEffect(() => {
        if (contract?.abacusContract) {
            const { account: accountData } = contract.abacusContract;
            if (accountData?.accountId) {
                setAccountId(accountData?.accountId);
            }

            const { contractTerms: contractTermsData } =
                contract.abacusContract;
            if (contractTermsData) {
                setContractTerms(contractTermsData);
            }
        }
    }, [contract]);

    const getRelatedLabels = () => {
        if (!isEmpty(state.attachmentsRelations)) {
            const { labelIds } = state.attachmentsRelations;
            if (!isEmpty(labelIds)) return labelIds;
        }
        return [];
    };
    const contractTermChangeHandler = (e: any) => {
        const {
            target: { name, value },
        } = e;

        dispatch({ type: SET_CONTRACT_TERM, name, value });
    };

    const multiLabelsChangeHandler = (e: any) => {
        const {
            target: { value },
        } = e;
        const attachments = value || [];
        dispatch({ type: SET_CONTRACT_TERM_ATTACHMENTS, attachments });
    };

    const labelChangeHandler = (e: any) => {
        const {
            target: { value },
        } = e;
        const relatedLabelIds = getRelatedLabels();
        if (isEmpty(relatedLabelIds) || !relatedLabelIds.includes(value)) {
            dispatch({
                type: SET_ATTACHMENTS_RELATIONS,
                attachmentsRelations: {
                    labelIds: [value?.toString()].filter(Boolean),
                },
            });
            dispatch({ type: SET_CONTRACT_TERM_ATTACHMENTS, attachments: [] });
        }
    };

    const productChangeHandler = (e: any) => {
        const {
            target: { value },
        } = e;
        const attachments = value || [];
        dispatch({ type: SET_CONTRACT_TERM_ATTACHMENTS, attachments });
    };

    const trackChangeHandler = (e: any) => {
        const {
            target: { value },
        } = e;
        const attachments = value || [];
        dispatch({ type: SET_CONTRACT_TERM_ATTACHMENTS, attachments });
    };

    useEffect(() => {
        if (state.attachments.length > 0 && state.conditions.length === 0)
            dispatch({ type: SET_DEFAULT_CONDITION });
    }, [state.attachments]);

    return (
        <>
            <Container fluid>
                <Row>
                    <Col sm={6}>
                        <Form.Group controlId="termName">
                            <Form.Label>Term Name</Form.Label>
                            <Form.Control
                                data-testid="termName"
                                name="contractTermName"
                                onChange={contractTermChangeHandler}
                                type="text"
                                value={state.contractTermName || ''}
                                maxLength={CONTRACT_TERM_NAME_CHAR_LIMIT}
                            />
                        </Form.Group>
                    </Col>
                    <Col sm={6}>
                        {termType === DISTRO_CONTRACT_TERM_TYPES.LABEL && (
                            <Form.Group id="labelSearch">
                                <Form.Label>Label</Form.Label>
                                <LabelMultiSelect
                                    onChange={multiLabelsChangeHandler}
                                    vendorCatalogIds={state.attachments}
                                />
                            </Form.Group>
                        )}
                        {[
                            DISTRO_CONTRACT_TERM_TYPES.PRODUCT,
                            DISTRO_CONTRACT_TERM_TYPES.TRACK,
                        ].includes(termType) && (
                            <Form.Group id="labelSearch">
                                <Form.Label>Label</Form.Label>
                                <LabelSelect
                                    onChange={labelChangeHandler}
                                    vendorCatalogIds={getRelatedLabels()}
                                />
                            </Form.Group>
                        )}
                    </Col>
                </Row>
                <Row>
                    <Col sm={12}>
                        {termType === DISTRO_CONTRACT_TERM_TYPES.PRODUCT && (
                            <Form.Group id="productSearch">
                                <Form.Label>Products</Form.Label>
                                <ProductMultiSelect
                                    accountId={accountId}
                                    contractTermId={contractTermId}
                                    contractTerms={contractTerms}
                                    onChange={productChangeHandler}
                                    productUpcs={state.attachments}
                                    labelIds={getRelatedLabels()}
                                    setErrors={setErrors}
                                />
                            </Form.Group>
                        )}
                        {termType === DISTRO_CONTRACT_TERM_TYPES.TRACK && (
                            <Form.Group id="trackSearch">
                                <Form.Label>Tracks</Form.Label>
                                <TrackMultiSelect
                                    accountId={accountId}
                                    contractTermId={contractTermId}
                                    contractTerms={contractTerms}
                                    onChange={trackChangeHandler}
                                    tracksIsrcs={state.attachments}
                                    labelIds={getRelatedLabels()}
                                    setErrors={setErrors}
                                />
                            </Form.Group>
                        )}
                    </Col>
                </Row>
            </Container>
            <Container fluid>
                {(state.attachments.length > 0 ||
                    state.conditions.length > 0) && (
                    <ContractTermsDistroConditionsList />
                )}
            </Container>
        </>
    );
};

export default ContractTermsDistroForm;
