import React, { useContext, useEffect, useState } from 'react';
import {
    Alert,
    FullscreenModal,
    UploadArea,
} from '@theorchard/suite-components';
import { isEmpty } from 'lodash-es';
import { ABACUS_ACTION_STATUSES } from '@theorchard/accounting-apps-shared';

import { AbacusDag } from 'src/apollo/definitions/globalTypes';
import { useStatementPeriodAdjustmentFilesAndStates } from 'src/apollo/queries/adjustment';
import { useDagRunTimesQuery } from 'src/apollo/queries/dag-run-times';
import { STATEMENT_PERIOD_ADJUSTMENT_UPLOAD_ACTIONS } from 'src/constants';
import { formatFile } from 'src/utils/adjustment-file';
import { AdjustmentsContext } from 'src/contexts/adjustments-context';

import type { UploadAreaInfoProps } from '@theorchard/suite-components';
import type { GetStatementPeriodAdjustmentFileAndStatesQuery } from 'src/apollo/queries/adjustment/__generated__/statement-period-adjustment-file-and-states';
import RunTimerTooltip from 'src/components/shared/run-timer-tooltip';

type AbacusStatementPeriodAdjustmentFile = NonNullable<
    GetStatementPeriodAdjustmentFileAndStatesQuery['abacusStatementPeriodAdjustmentFile']
>;
type ActionStateTypes =
    AbacusStatementPeriodAdjustmentFile['actionStates'] extends
        | (infer T)[]
        | null
        ? T
        : null;

export const AdjustmentsUploadLoadingScreen = () => {
    const {
        statementPeriodId,
        statementPeriodAdjustmentFileId,
        setModalState,
        setAdjustmentFile,
    } = useContext(AdjustmentsContext);

    const [uploadStatus, setUploadStatus] = useState<
        ActionStateTypes | undefined | null
    >(undefined);

    const {
        data: fileData,
        startPolling: startApprovalPolling,
        stopPolling: stopApprovalPolling,
    } = useStatementPeriodAdjustmentFilesAndStates(
        statementPeriodId,
        statementPeriodAdjustmentFileId.toString()
    );

    const { data: uploadFileDagRunTimes } = useDagRunTimesQuery(
        AbacusDag.ADJUSTMENT_FILE_UPLOAD
    );

    const avgUploadTime =
        uploadFileDagRunTimes?.abacusDagRunTimes.averageRunTimeSeconds;

    const p95UploadTime =
        uploadFileDagRunTimes?.abacusDagRunTimes.p95RunTimeSeconds;

    useEffect(() => {
        if (!isEmpty(uploadStatus)) {
            if (
                uploadStatus!.actionStatus === ABACUS_ACTION_STATUSES.INIT ||
                uploadStatus!.actionStatus === ABACUS_ACTION_STATUSES.RUNNING
            ) {
                startApprovalPolling(2000);
            }

            if (uploadStatus!.actionStatus === ABACUS_ACTION_STATUSES.ERROR) {
                stopApprovalPolling();
                setAdjustmentFile(formatFile(fileData));
                setModalState(ABACUS_ACTION_STATUSES.ERROR);
            }

            if (
                uploadStatus!.actionStatus === ABACUS_ACTION_STATUSES.COMPLETE
            ) {
                stopApprovalPolling();
                setAdjustmentFile(formatFile(fileData));
                setModalState(ABACUS_ACTION_STATUSES.COMPLETE);
            }
        }
    }, [uploadStatus]);

    useEffect(() => {
        if (fileData && fileData.abacusStatementPeriodAdjustmentFile) {
            const { actionStates } =
                fileData.abacusStatementPeriodAdjustmentFile;

            if (!isEmpty(actionStates)) {
                setUploadStatus(
                    actionStates?.find(
                        action =>
                            action!.actionName ===
                            STATEMENT_PERIOD_ADJUSTMENT_UPLOAD_ACTIONS.UPLOAD_FILE
                    )
                );
            }
        }
    }, [fileData]);

    const getUploadAreaInfo = (): UploadAreaInfoProps => {
        return {
            illustration: 'spinner',
            title: 'Validating Your File',
            description: 'Checking for data integrity...',
        };
    };

    const renderUploadArea = () => (
        <UploadArea
            disabled
            inputId="browser-upload-loading"
            info={getUploadAreaInfo()}
            onUpload={() => {
                return;
            }}
            testId="AdjustmentsUploadLoadingArea"
            variant="large"
        />
    );

    return (
        <>
            <FullscreenModal.Title title="Uploading File" />
            <FullscreenModal.Body>
                <Alert
                    testId="AdjustmentsUploadingFileAlert"
                    variant="information"
                    text={
                        <span>
                            <b>
                                Please stay on this page while your file
                                uploads.
                            </b>
                            <br />
                            Closing or leaving this page will cancel your
                            upload. To ensure it completes successfully, please
                            remain here until it finishes.
                        </span>
                    }
                />
                {avgUploadTime && p95UploadTime ? (
                    <RunTimerTooltip
                        avgRunTime={avgUploadTime}
                        p95RunningTime={p95UploadTime}
                        tooltipLocation="bottom"
                        testId="AdjustmentsUploadingRunTimerTooltip"
                    >
                        {renderUploadArea()}
                    </RunTimerTooltip>
                ) : (
                    renderUploadArea()
                )}
            </FullscreenModal.Body>
        </>
    );
};
