import React, { useEffect, useReducer, useState } from 'react';
import { Alert, LoadingPageIndicator } from '@theorchard/suite-components';
import { useFeatureFlag } from '@theorchard/suite-frontend';
import { isEmpty } from 'lodash-es';
import { useParams } from 'react-router-dom';
import {
    AbacusContractPartyTargetType,
    TransactionTypeGroupAdmin,
} from 'src/apollo/definitions/globalTypes';
import { useContract } from 'src/apollo/queries/contract';
import { useContractPartyList } from 'src/apollo/queries/contract-party';
import { useStoreList } from 'src/apollo/queries/stores';
import { useTransactionTypesWithGroups } from 'src/apollo/queries/transaction-types';
import { ContractAdvances } from 'src/components/contract-advance-list/contract-advances';
import { ContractDetailHeader } from 'src/components/contract-detail/contract-detail-header';
import ContractEarningsTransfers from 'src/components/contract-earnings-transfer-list/contract-earnings-transfers';
import { ContractFlowthrough } from 'src/components/contract-detail/contract-flowthrough';
import { ContractGeneralDetailSection } from 'src/components/contract-detail/contract-general-detail-section';
import { ContractMechanicalDeductions } from 'src/components/contract-detail/contract-mechanical-deductions';
import { ContractNotes } from 'src/components/contract-detail/contract-notes';
import { ContractPhysicalReserve } from 'src/components/contract-detail/contract-physical-reserve';
import { ContractSummaryNotes } from 'src/components/contract-detail/contract-summary-notes';
import { ContractTerms } from 'src/components/contract-detail/contract-terms';
import { NrContractContributors } from 'src/components/contract-detail/nr-contract-contributors';
import { NrContractContributorsList } from 'src/components/contract-detail/nr-contract-contributors-list';
import { NrContractTerms } from 'src/components/contract-detail/nr-contract-terms';
import { USER_FEATURES } from 'src/constants';
import {
    CONTRACT_TERM_TYPES,
    CONTRACT_TYPES,
    RECEIVE_CONTRACT_TERMS,
    RECEIVE_STORES,
    RECEIVE_TRANSACTION_TYPES,
} from 'src/constants';
import { ContractLifecycleContext } from 'src/contexts/contract-lifecycle-context';
import { ContractTermContext } from 'src/contexts/contract-term-context';
import {
    initialTermsState,
    reducer,
} from 'src/reducers/contract-term/contract-terms-details-reducer';
import { generalSectionStyling } from './constants';
import type {
    AbacusContract,
    AbacusContractAccount,
    AbacusContractLifecycle,
} from 'src/types/abacus-contract';
import type { ContractLifecycle } from 'src/types/abacus-contract-lifecycle';
import type { TransactionType } from 'src/types/abacus-contract-term';
import './styles.scss';

export const ContractDetail = () => {
    const { contractId } = useParams<{ contractId: string }>();

    const [state, dispatch] = useReducer(reducer, initialTermsState);
    const [contract, setContract] = useState<AbacusContract | null>(null);
    const [isEditingContractRenewalRules, setIsEditingContractRenewalRules] =
        useState(false);
    const [isTerminatingContract, setIsTerminatingContract] = useState(false);
    const { data, error, loading } = useContract(contractId);
    const { data: stores } = useStoreList();
    const { data: transactionTypes } = useTransactionTypesWithGroups(
        TransactionTypeGroupAdmin.PRESENTATIONAL
    );
    const [nrContractContributorsTotal, setNrContractContributorsTotal] =
        useState(0);

    const setContractLifecycle = (lifecycle: ContractLifecycle) => {
        if (contract) {
            setContract({
                ...contract,
                lifecycle: lifecycle as AbacusContractLifecycle,
            });
        }
    };

    const contractPartyFilterValues = {
        contractId,
        limit: 100,
        offset: 0,
        targetType: AbacusContractPartyTargetType.CONTRIBUTOR,
    };

    const isFeatureNrContractPageRedesignEnabled = useFeatureFlag(
        USER_FEATURES.ABACUS_NR_CONTRACT_PAGE_REDESIGN
    );

    let contractPartyList;
    let isContractPartyListLoading;
    if (!isFeatureNrContractPageRedesignEnabled) {
        ({ data: contractPartyList, loading: isContractPartyListLoading } =
            useContractPartyList(contractPartyFilterValues));
    }

    let contractData: AbacusContract | null = null;
    let baseTerms = [];
    let nrTerms = [];
    const storeList: string[] = [];
    let trackExceptions = [];
    let productExceptions = [];
    let labelTerms = [];
    let trackTerms = [];
    let productTerms = [];
    const transactionTypeList: TransactionType[] = [];

    const isFeatureEarningsTransfersEnabled = useFeatureFlag(
        USER_FEATURES.ABACUS_CONTRACT_EARNINGS_TRANSFERS
    );

    useEffect(() => {
        if (stores) {
            stores.deliveryStoresV2.items.forEach(store => {
                storeList[parseInt(store.id, 10)] = store.name;
            });
            dispatch({ type: RECEIVE_STORES, stores: storeList });
        }
    }, [stores]);

    useEffect(() => {
        if (transactionTypes) {
            transactionTypes.transactionTypes?.forEach(transactionType => {
                transactionTypeList[parseInt(transactionType.txnTypeId, 10)] = {
                    txnTypeName: transactionType.txnTypeName,
                    txnTypeCode: transactionType.txnTypeCode,
                    txnTypeId: transactionType.txnTypeId,
                    transactionTypeGroup: transactionType.transactionTypeGroup,
                };
            });
            dispatch({
                type: RECEIVE_TRANSACTION_TYPES,
                transactionTypes: transactionTypeList,
            });
        }
    }, [transactionTypes]);

    useEffect(() => {
        if (!isEmpty(data) && !isEmpty(data.abacusContract)) {
            contractData = data.abacusContract;
            const contractTerms = contractData.contractTerms;

            setContract(contractData);

            if (contractTerms) {
                baseTerms = contractTerms.filter(term => term.isBaseTerm);

                trackExceptions = contractTerms.filter(
                    term =>
                        !term.isBaseTerm &&
                        term.termType === CONTRACT_TERM_TYPES.TRACK
                );

                productExceptions = contractTerms.filter(
                    term =>
                        !term.isBaseTerm &&
                        term.termType === CONTRACT_TERM_TYPES.PRODUCT
                );

                nrTerms = contractTerms.filter(
                    term =>
                        term.termType ===
                            CONTRACT_TERM_TYPES.CONTRIBUTOR_SCHEDULE ||
                        term.termType ===
                            CONTRACT_TERM_TYPES.CONTRIBUTION_SCHEDULE
                );

                labelTerms = contractTerms.filter(
                    term => term.termType === CONTRACT_TERM_TYPES.LABEL
                );

                productTerms = contractTerms.filter(
                    term => term.termType === CONTRACT_TERM_TYPES.PRODUCT
                );

                trackTerms = contractTerms.filter(
                    term => term.termType === CONTRACT_TERM_TYPES.TRACK
                );

                dispatch({
                    type: RECEIVE_CONTRACT_TERMS,
                    contractTerms: {
                        baseTerms,
                        trackExceptions,
                        productExceptions,
                        nrTerms,
                        labelTerms,
                        productTerms,
                        trackTerms,
                    },
                });
            }
        }
    }, [data]);

    const ContractFlowthroughSection = () => {
        if (contract?.contractType === CONTRACT_TYPES.NEIGHBOURING_RIGHTS)
            return null;

        return (
            <section className="ContractDetail-section">
                <ContractFlowthrough
                    contractFlowthrough={contract?.contractFlowthrough ?? null}
                />
            </section>
        );
    };

    return (
        <div className="ContractDetail" data-testid="contractDetailPage">
            {error && <Alert variant="error" text={error.message} />}
            <ContractDetailHeader
                contract={contract}
                loading={loading}
                setIsEditingContractRenewalRules={
                    setIsEditingContractRenewalRules
                }
                setIsTerminatingContract={setIsTerminatingContract}
            />
            {loading ? (
                <LoadingPageIndicator />
            ) : (
                <ContractLifecycleContext.Provider
                    value={{
                        contract: contract ?? ({} as AbacusContract),
                        isEditingContractRenewalRules:
                            isEditingContractRenewalRules,
                        setIsEditingContractRenewalRules:
                            setIsEditingContractRenewalRules,
                        isTerminatingContract: isTerminatingContract,
                        setIsTerminatingContract: setIsTerminatingContract,
                        setContractLifecycle: setContractLifecycle,
                    }}
                >
                    <section
                        className="ContractDetail-section"
                        style={{ ...generalSectionStyling }}
                    >
                        <ContractSummaryNotes
                            contractName={contract?.contractName ?? ''}
                            summaryNote={contract?.summaryNote ?? ''}
                        />
                    </section>
                    <section
                        className="ContractDetail-section"
                        style={{ ...generalSectionStyling }}
                    >
                        <ContractGeneralDetailSection
                            account={
                                contract?.account ??
                                ({} as AbacusContractAccount)
                            }
                            contractName={contract?.contractName ?? ''}
                            contractType={contract?.contractType ?? ''}
                            initialStartDate={contract?.initialStartDate}
                            referenceSigningEntityName={
                                contract?.referenceSigningEntity?.legalName ??
                                ''
                            }
                            runControllerName={
                                contract?.runController?.runControllerName ?? ''
                            }
                            runControllerId={
                                contract?.runController?.runControllerId?.toString() ??
                                ''
                            }
                            isExcludedFromAccountingRun={
                                contract?.isExcludedFromAccountingRun
                            }
                            isPaythroughContract={Boolean(
                                contract?.isPaythroughContract
                            )}
                            isPrimaryContract={Boolean(
                                contract?.isPrimaryContract
                            )}
                            executionDate={contract?.executionDate}
                            sapProfitCenterDisplayName={
                                contract?.sapProfitCenter?.displayName
                            }
                        />
                    </section>
                    <ContractFlowthroughSection />
                    {isFeatureEarningsTransfersEnabled && (
                        <section className="ContractDetail-section">
                            <ContractEarningsTransfers />
                        </section>
                    )}
                    <section className="ContractDetail-section ContractDetail-advance-section">
                        <ContractAdvances
                            accountPaymentCurrency={
                                contract?.account?.accountPaymentTerm
                                    ?.currencyCode
                            }
                            contractType={contract?.contractType}
                            runControllerName={
                                contract?.runController?.runControllerName
                            }
                        />
                    </section>
                    {contract?.contractType === CONTRACT_TYPES.DISTRIBUTION && (
                        <ContractTermContext.Provider
                            value={{ state, dispatch }}
                        >
                            <ContractTerms />
                        </ContractTermContext.Provider>
                    )}
                    {contract?.contractType ===
                        CONTRACT_TYPES.NEIGHBOURING_RIGHTS &&
                        (isFeatureNrContractPageRedesignEnabled ? (
                            <section className="ContractDetail-section">
                                <div className="ContractDetail-nr-contributors-section">
                                    <NrContractContributorsList
                                        nrContractContributorsTotal={
                                            nrContractContributorsTotal
                                        }
                                        setNrContractContributorsTotal={
                                            setNrContractContributorsTotal
                                        }
                                    />
                                </div>
                                <div className="ContractDetail-nr-terms-section">
                                    <ContractTermContext.Provider
                                        value={{ state, dispatch }}
                                    >
                                        <NrContractTerms
                                            isButtonEnabled={Boolean(
                                                nrContractContributorsTotal
                                            )}
                                            isFeatureNrContractPageRedesignEnabled={
                                                isFeatureNrContractPageRedesignEnabled
                                            }
                                        />
                                    </ContractTermContext.Provider>
                                </div>
                            </section>
                        ) : (
                            <section
                                className="ContractDetail-section"
                                style={{ ...generalSectionStyling }}
                            >
                                <NrContractContributors
                                    contractPartyList={
                                        contractPartyList?.abacusContractParties
                                            ?.items || []
                                    }
                                    isContractPartyListLoading={Boolean(
                                        isContractPartyListLoading
                                    )}
                                />
                                <ContractTermContext.Provider
                                    value={{ state, dispatch }}
                                >
                                    <NrContractTerms
                                        isButtonEnabled={Boolean(
                                            contractPartyList
                                                ?.abacusContractParties
                                                ?.totalCount
                                        )}
                                        isFeatureNrContractPageRedesignEnabled={
                                            isFeatureNrContractPageRedesignEnabled
                                        }
                                    />
                                </ContractTermContext.Provider>
                            </section>
                        ))}
                    {contract?.contractType === CONTRACT_TYPES.DISTRIBUTION && (
                        <section className="ContractDetail-section">
                            <ContractMechanicalDeductions
                                contractId={contract?.contractId}
                                mechanicalDeductions={
                                    contract?.mechanicalDeductions
                                }
                            />
                        </section>
                    )}
                    {contract?.contractType === CONTRACT_TYPES.DISTRIBUTION && (
                        <section className="ContractDetail-section">
                            <ContractPhysicalReserve
                                contractId={contractId}
                                physicalReserve={contract.reserve}
                            />
                        </section>
                    )}
                    <section className="ContractDetail-section">
                        <ContractNotes
                            contractId={contractId}
                            generalNote={contract?.generalNote ?? ''}
                        />
                    </section>
                </ContractLifecycleContext.Provider>
            )}
        </div>
    );
};
