// 'use no memo' — see src/components/reference/reference.tsx for rationale.
// Page.Nav + Page.Body tab pattern depends on parent re-render on URL change.
'use no memo';

import React, { useEffect, useState } from 'react';
import {
    Alert,
    Col,
    LoadingIndicator,
    Row,
} from '@theorchard/suite-components';
import { Page } from '@theorchard/suite-frontend';
import { useParams } from 'react-router-dom';
import { useStatementPeriod } from 'src/apollo/queries/statement-periods';
import {
    RELEASE_RESERVES,
    STATEMENT_PERIOD_ACTIONS,
    STATEMENT_PERIOD_ADJUSTMENT_UPLOAD_ACTIONS,
} from 'src/constants';
import { getMostRecentAbacusEvent } from 'src/utils/abacus-events';
import { isActionComplete as isAbacusStateActionComplete } from 'src/utils/action-states';
import { PageHeader } from 'src/components/shared/pageHeader';
import { CloseStatementPeriodButton } from './close-statement-period-button';
import { ReleasePhysicalReservesButton } from './release-physical-reserves-button';
import { ShowCustomerAccounting } from './show-customer-accounting';
import { UploadExchangeRates } from './upload-exchange-rates';
import type { GetStatementPeriodQuery } from 'src/apollo/queries/statement-periods/__generated__/statement-period';
import type { AbacusEvent } from 'src/types/abacus-event';
import { useStatementBreadcrumbs } from 'src/hooks/breadcrumbs/statementPeriod';
import {
    ABACUS_ACTION_STATUSES,
    ABACUS_ACTIONS,
} from '@theorchard/accounting-apps-shared';
import './styles.scss';

type AbacusStatementPeriod = NonNullable<
    GetStatementPeriodQuery['abacusStatementPeriod']
>;
type AbacusStatementPaymentEntity = NonNullable<
    AbacusStatementPeriod['paymentEntities'][0]
>;
type AbacusActionState = NonNullable<
    AbacusStatementPaymentEntity['actionStates']
>[0];
type AbacusStatementPeriodFile = NonNullable<
    AbacusStatementPeriod['statementPeriodAdjustmentFiles'][0]
>;

const StatementPeriodDetail: React.FC = () => {
    const { statementPeriodId } = useParams<{ statementPeriodId: string }>();
    const { data, loading } = useStatementPeriod(statementPeriodId);

    const [error, setError] = useState<string | null>(null);

    const [actionStates, setActionStates] = useState<any>(null);
    const abacusEvents = data?.abacusStatementPeriod?.abacusEvents;
    const isPeriodClosed =
        data?.abacusStatementPeriod?.statementPeriodStatus === 'closed';
    const breadcrumbs = useStatementBreadcrumbs();

    useEffect(() => {
        if (data?.abacusStatementPeriod?.actionStates)
            setActionStates(data?.abacusStatementPeriod?.actionStates);
    }, [data]);

    if (loading || !actionStates) return <LoadingIndicator />;

    const getAbacusEventByName = (name: string) => {
        if (!abacusEvents) return null;

        const events = abacusEvents.filter(event => event?.eventName === name);
        return getMostRecentAbacusEvent(events as AbacusEvent[]);
    };

    const getActionStateByName = (name: string) =>
        actionStates.find(
            (actionState: any) => actionState?.actionName === name
        );

    const isActionComplete = (name: string) => {
        const actionState = getActionStateByName(name);
        return actionState?.actionStatus === ABACUS_ACTION_STATUSES.COMPLETE;
    };

    const areCustomerAccountingActionsComplete = (
        paymentEntities: AbacusStatementPaymentEntity[] | undefined
    ) =>
        paymentEntities
            ? paymentEntities.every(
                  ({ isVisibleToCustomer }: AbacusStatementPaymentEntity) =>
                      isVisibleToCustomer
              )
            : false;

    const areAllAdjustmentFilesApplied = (
        statementPeriodAdjustmentFiles?: AbacusStatementPeriodFile[]
    ) => {
        if (statementPeriodAdjustmentFiles)
            return statementPeriodAdjustmentFiles?.every(
                (adjustmentFile: AbacusStatementPeriodFile) => {
                    const { actionStates } = adjustmentFile;
                    const isUploadComplete = isAbacusStateActionComplete(
                        actionStates,
                        STATEMENT_PERIOD_ADJUSTMENT_UPLOAD_ACTIONS.UPLOAD_FILE
                    );
                    if (!isUploadComplete) return true;

                    const isImportComplete = isAbacusStateActionComplete(
                        actionStates,
                        STATEMENT_PERIOD_ADJUSTMENT_UPLOAD_ACTIONS.IMPORT_FILE
                    );

                    if (isUploadComplete && !isImportComplete) return true;

                    const areAllActionsCompleted = actionStates?.every(
                        (state: AbacusActionState | null) =>
                            state?.actionStatus ===
                            ABACUS_ACTION_STATUSES.COMPLETE
                    );

                    return areAllActionsCompleted;
                }
            );

        return true;
    };

    const areCloseBalancesActionsComplete = (
        paymentEntities: AbacusStatementPaymentEntity[] | undefined
    ) => {
        if (paymentEntities)
            return paymentEntities?.every(paymentEntity => {
                const { actionStates } = paymentEntity;
                const isCloseBalanceComplete = isAbacusStateActionComplete(
                    actionStates,
                    STATEMENT_PERIOD_ACTIONS.CLOSE_BALANCE
                );
                return isCloseBalanceComplete;
            });

        return true;
    };

    return (
        <>
            <PageHeader
                title={data?.abacusStatementPeriod?.statementPeriodName}
                breadcrumbs={breadcrumbs}
            />
            <Page.Body className="StatementPeriodDetail">
                {
                    <div className="StatementPeriodDetail-container">
                        <Row>
                            <Col>
                                {error && (
                                    <Alert variant="error" text={error} />
                                )}
                            </Col>
                        </Row>
                        {getActionStateByName(
                            STATEMENT_PERIOD_ACTIONS.STATEMENT_PERIOD_CLOSE
                        )?.actionStatus === ABACUS_ACTION_STATUSES.ERROR && (
                            <Row>
                                <Alert.Container
                                    className="StatementPeriodDetail-failed-attachments-banner"
                                    header="Statement Attachment Failure Notification"
                                >
                                    <Alert
                                        className="contact-msg"
                                        variant="information"
                                        text="Please contact the Accounting Tech Team to resolve this issue."
                                    />
                                </Alert.Container>
                            </Row>
                        )}
                        <Row className="StatementPeriodDetail-content">
                            <Col sm={4}>
                                <h3>Status / Actions</h3>
                                <div className="StatementPeriodDetail-actionBox StatementPeriodDetail-actionLinks">
                                    <UploadExchangeRates
                                        exchangeRatesUploaded={isActionComplete(
                                            ABACUS_ACTIONS.UPLOAD_EXCHANGE_RATES
                                        )}
                                        setError={setError}
                                    />
                                    <ReleasePhysicalReservesButton
                                        abacusEvent={getAbacusEventByName(
                                            RELEASE_RESERVES.EVENT_NAME
                                        )}
                                        actionState={getActionStateByName(
                                            STATEMENT_PERIOD_ACTIONS.RELEASE_RESERVES
                                        )}
                                        setError={setError}
                                    />
                                    <CloseStatementPeriodButton
                                        adjustmentsAreApplied={areAllAdjustmentFilesApplied(
                                            data?.abacusStatementPeriod
                                                ?.statementPeriodAdjustmentFiles
                                        )}
                                        areCloseBalancesActionsComplete={areCloseBalancesActionsComplete(
                                            data?.abacusStatementPeriod
                                                ?.paymentEntities
                                        )}
                                        exchangeRatesAreUploaded={isActionComplete(
                                            STATEMENT_PERIOD_ACTIONS.UPLOAD_EXCHANGE_RATES
                                        )}
                                        physicalReservesAreReleased={isActionComplete(
                                            STATEMENT_PERIOD_ACTIONS.RELEASE_RESERVES
                                        )}
                                        customerAccountingActionsCompleted={areCustomerAccountingActionsComplete(
                                            data?.abacusStatementPeriod
                                                ?.paymentEntities
                                        )}
                                        isPeriodClosed={isPeriodClosed}
                                        setError={setError}
                                    />
                                </div>
                            </Col>
                        </Row>
                        <hr />
                        <Row>
                            <Col sm="12">
                                <ShowCustomerAccounting
                                    statementPeriod={
                                        data?.abacusStatementPeriod
                                    }
                                />
                            </Col>
                        </Row>
                    </div>
                }
            </Page.Body>
        </>
    );
};

export default StatementPeriodDetail;
