import React, { useContext, useEffect, useState } from 'react';
import { Button, Col, Form, Label, Row } from '@theorchard/suite-components';
import { GlyphIcon } from '@theorchard/suite-icons';
import { has } from 'lodash-es';
import { useParams } from 'react-router-dom';
import { AbacusContractPartyTargetType } from 'src/apollo/definitions/globalTypes';
import { useContractPartyListLazyQuery } from 'src/apollo/queries/contract-party';
import { NR_TERM_TYPES_MAP } from 'src/apollo/type-constants/contract';
import { HAS_CONTRIBUTOR_ONLY_SCHEDULES } from 'src/apollo/type-constants/contract';
import { SelectedTermTypeDropDown } from 'src/components/contract-terms-form-nr/selected-term-type-dropdown';
import { NrTermTypeSelect } from 'src/components/shared/nr-term-type-select';
import {
    CHANGE_CONTRACT_TERM_TYPE,
    CONTRACT_TERM_TYPES,
    EMPTY_TERM_CONDITIONS,
    SET_CONTRACT_TERM,
    SET_ERRORS,
} from 'src/constants';
import { ContractTermContext } from 'src/contexts/contract-term-context';
import type { GetContractPartyListQuery } from 'src/apollo/queries/contract-party/__generated__/get-contract-party-list';

type AbacusContractPartyItem = NonNullable<
    GetContractPartyListQuery['abacusContractParties']['items'][0]
>;
interface ContractPartyFilterValues {
    contractId: string;
    limit: number;
    offset: number;
    targetType: AbacusContractPartyTargetType;
    includeOnlySchedules?: boolean;
}

export const NrContractTermsFormFields: React.FC = () => {
    const { contractId, contractTermId } = useParams<{
        contractId: string;
        contractTermId: string;
    }>();
    const { state, dispatch } = useContext(ContractTermContext);
    const [contractPartyFilterValues, setContractPartyFilterValues] =
        useState<ContractPartyFilterValues>({
            contractId,
            limit: 100,
            offset: 0,
            targetType: AbacusContractPartyTargetType.CONTRIBUTOR,
        });
    const [selectedTermTypeDropDownList, setSelectedTermTypeDropDownList] =
        useState<{ label: string; value: string }[] | []>([]);

    const {
        data: contractPartyList,
        error: contractPartyError,
        loading: contractPartyListLoading,
        getAbacusContractPartyList,
    } = useContractPartyListLazyQuery();

    const formatSelectedTermTypeDropDownList = (
        items: AbacusContractPartyItem[]
    ) => {
        let dropDownList: { label: string; value: string }[] | [] = [];

        items?.forEach(({ contractPartyObject }: AbacusContractPartyItem) => {
            if (!contractPartyObject) return;

            const schedulesList =
                contractPartyObject?.__typename === 'NrContributor'
                    ? contractPartyObject?.abacusSchedules?.map(
                          abacusSchedule => {
                              const label =
                                  state.termType ===
                                  CONTRACT_TERM_TYPES.CONTRIBUTOR_SCHEDULE
                                      ? contractPartyObject.name || ''
                                      : `${abacusSchedule.scheduleName} (${abacusSchedule.scheduleAttachments.totalCount})`;

                              return {
                                  label: label,
                                  value: abacusSchedule.scheduleId,
                              };
                          }
                      )
                    : [];
            dropDownList = [...dropDownList, ...schedulesList];
        });
        setSelectedTermTypeDropDownList(dropDownList);
    };

    useEffect(() => {
        if (state.termType) {
            dispatch({
                type: SET_CONTRACT_TERM,
                name: 'scheduleIds',
                value: [],
            });
            setSelectedTermTypeDropDownList([]);
            getAbacusContractPartyList(contractPartyFilterValues);
        }
    }, [contractPartyFilterValues.includeOnlySchedules]);

    useEffect(() => {
        if (
            state.termType &&
            !has(contractPartyFilterValues, 'includeOnlySchedules')
        )
            getAbacusContractPartyList({
                ...contractPartyFilterValues,
                includeOnlySchedules:
                    HAS_CONTRIBUTOR_ONLY_SCHEDULES[state.termType],
            });
    }, [contractTermId, state.termType]);

    useEffect(() => {
        if (contractPartyList && contractPartyList?.abacusContractParties) {
            const { items } = contractPartyList.abacusContractParties;
            formatSelectedTermTypeDropDownList(items);
        }
    }, [contractPartyList]);

    useEffect(() => {
        if (contractPartyError?.message)
            dispatch({
                type: SET_ERRORS,
                error: [contractPartyError?.message],
            });
    }, [contractPartyError]);

    const changeHandler = (e: any) => {
        const {
            target: { name, value, index },
            remove,
        } = e;
        if (name === 'scheduleIds') {
            let scheduleIds: string[] | [] = state.scheduleIds;
            if (remove) {
                scheduleIds = scheduleIds.filter(
                    (currentValue: string, currentIndex: number) =>
                        currentValue !== value && currentIndex !== index
                );
            } else {
                scheduleIds[index] = value;
            }
            dispatch({
                type: SET_CONTRACT_TERM,
                name: 'scheduleIds',
                value: scheduleIds,
            });
        } else dispatch({ type: SET_CONTRACT_TERM, name, value });

        if (name === 'termType') {
            dispatch({ type: EMPTY_TERM_CONDITIONS });

            if (contractTermId)
                dispatch({
                    type: CHANGE_CONTRACT_TERM_TYPE,
                    isTermTypeChanged: true,
                });

            setContractPartyFilterValues({
                ...contractPartyFilterValues,
                includeOnlySchedules: HAS_CONTRIBUTOR_ONLY_SCHEDULES[value],
            });
        }
    };

    const filterNonAddedScheduleIds = (currentValue: string) =>
        selectedTermTypeDropDownList.filter(
            ({ value }) =>
                value == currentValue || !state.scheduleIds.includes(value)
        );

    return (
        <>
            <Row>
                <Col sm={1}>
                    <Label text="Term Name" />
                </Col>
                <Col sm={5}>
                    <Form.Control
                        data-testid="termNameTestId"
                        name="contractTermName"
                        onChange={(e: any) => changeHandler(e)}
                        type="text"
                        value={state.contractTermName || ''}
                    />
                </Col>
            </Row>
            <Row>
                <Col sm={1}>
                    <Label text="Term Type" />
                </Col>
                <Col sm={5}>
                    <NrTermTypeSelect
                        id="nrTermType"
                        isClearable={false}
                        name="termType"
                        placeholder="- Select -"
                        onChange={(e: any) =>
                            changeHandler({
                                target: {
                                    name: 'termType',
                                    value: e && e.value,
                                },
                            })
                        }
                        value={state.termType || ''}
                    />
                </Col>
            </Row>
            {state?.termType && (
                <>
                    {state.scheduleIds.length ? (
                        state.scheduleIds.map(
                            (value: string, index: number) => (
                                <Row
                                    key={index}
                                    data-testid="term-schedules-row"
                                >
                                    <Col sm={1}>
                                        {index == 0 && (
                                            <Label
                                                text={
                                                    NR_TERM_TYPES_MAP[
                                                        state.termType
                                                    ]
                                                }
                                            />
                                        )}
                                    </Col>
                                    <Col sm={5}>
                                        <SelectedTermTypeDropDown
                                            className="NrContractTermsForm-term-schedules"
                                            dropDownOptions={filterNonAddedScheduleIds(
                                                value
                                            )}
                                            id="nrTermSchedules"
                                            isClearable={false}
                                            name="scheduleIds"
                                            placeholder="- Select -"
                                            onChange={(e: any) =>
                                                changeHandler({
                                                    target: {
                                                        name: 'scheduleIds',
                                                        value: e && e.value,
                                                        index,
                                                    },
                                                })
                                            }
                                            value={value}
                                            isLoading={contractPartyListLoading}
                                        />
                                    </Col>
                                    <Col sm={1}>
                                        {index > 0 && (
                                            <div
                                                className="NrContractTermsForm-term-remove-schedules"
                                                data-testid="remove-schedules"
                                                onClick={(e: any) =>
                                                    changeHandler({
                                                        target: {
                                                            name: 'scheduleIds',
                                                            value: e && e.value,
                                                            index,
                                                        },
                                                        remove: true,
                                                    })
                                                }
                                            >
                                                <GlyphIcon
                                                    name="trash"
                                                    size={16}
                                                />
                                            </div>
                                        )}
                                    </Col>
                                </Row>
                            )
                        )
                    ) : (
                        <Row>
                            <Col sm={1}>
                                <Label
                                    text={NR_TERM_TYPES_MAP[state.termType]}
                                />
                            </Col>
                            <Col sm={5}>
                                <SelectedTermTypeDropDown
                                    className="NrContractTermsForm-term-schedules"
                                    dropDownOptions={
                                        selectedTermTypeDropDownList
                                    }
                                    id="nrTermSchedules"
                                    isClearable={false}
                                    name="scheduleIds"
                                    placeholder="- Select -"
                                    onChange={(e: any) =>
                                        changeHandler({
                                            target: {
                                                name: 'scheduleIds',
                                                value: e && e.value,
                                                index: 0,
                                            },
                                        })
                                    }
                                    value={
                                        state.scheduleIds &&
                                        state.scheduleIds[0]
                                    }
                                    isLoading={contractPartyListLoading}
                                />
                            </Col>
                        </Row>
                    )}
                    {selectedTermTypeDropDownList.length > 1 && (
                        <Row>
                            <Col sm={1}></Col>
                            <Col sm={5}>
                                <Button
                                    className="NrContractTermsForm-add-new-term"
                                    onClick={() =>
                                        changeHandler({
                                            target: {
                                                name: 'scheduleIds',
                                                value: null,
                                                index:
                                                    state.scheduleIds.length ||
                                                    1,
                                            },
                                        })
                                    }
                                    variant="quartenary"
                                >
                                    + ADD ANOTHER
                                </Button>
                            </Col>
                        </Row>
                    )}
                </>
            )}
        </>
    );
};
