import React, { useEffect, useState } from 'react';
import { useApolloClient } from '@apollo/client';
import { Button, useToast } from '@theorchard/suite-components';
import { useHistory, useLocation } from 'react-router-dom';

import {
    inProgressAdjustmentsFiles,
    preExistingAdjustmentFiles,
} from 'src/apollo/reactive-vars/adjustment-files-status';
import { useInProgressAutoGenerateAdjustmentFile } from 'src/apollo/queries/adjustment';
import { fileGenerationFailedMessage } from 'src/apollo/type-constants/adjustment';
import AdjustmentsImportModal from 'src/components/adjustments/adjustments-import-modal/adjustments-import-modal';
import AdjustmentsList from 'src/components/adjustments/adjustments-list';
import { PageHeader } from 'src/components/shared/pageHeader';
import { USER_FEATURES } from 'src/constants';
import { isFeatureFlagEnabled } from 'src/utils/feature-flag';
import { generateAdjustments } from 'src/urls/frontend-royalties';
import { GetInProgressAutoAdjustmentFileQuery } from 'src/apollo/queries/adjustment/__generated__/get-in-progress-adjustment-file';
import { InProgressAdjustmentsFile } from 'src/types/adjustment-file';
import './styles.scss';

type AbacusInProgressAutoAdjustmentFile = NonNullable<
    NonNullable<
        GetInProgressAutoAdjustmentFileQuery['abacusInProgressAutoAdjustmentFile']
    >[number]
>;

export const Adjustments: React.FC = () => {
    const history = useHistory();
    const [isModalOpen, setIsModalOpen] = useState<boolean>(false);
    const [autoGeneratedAdjustmentFiles, setAutoGeneratedAdjustmentFiles] =
        useState<Array<AbacusInProgressAutoAdjustmentFile | null>>([]);
    const [retryBatch, setRetryBatch] = useState<number>(0);
    const [emptyInProgressCount, setEmptyInProgressCount] = useState<number>(0);

    const client = useApolloClient();

    const toast = useToast();

    const handleModalOpen = () => {
        setIsModalOpen(true);
    };

    const isAutoGenerateEnabled = isFeatureFlagEnabled(
        USER_FEATURES.ABACUS_AUTO_GENERATE_ADJUSTMENTS_FLOWTHROUGH
    );

    const { data, loading, startPolling, stopPolling, networkStatus } =
        useInProgressAutoGenerateAdjustmentFile();

    useEffect(() => {
        if (data && data?.abacusInProgressAutoAdjustmentFile) {
            setAutoGeneratedAdjustmentFiles(
                data?.abacusInProgressAutoAdjustmentFile ?? []
            );

            if (data?.abacusInProgressAutoAdjustmentFile?.length > 0) {
                const test = data?.abacusInProgressAutoAdjustmentFile ?? [];
                preExistingAdjustmentFiles(test);
            }
        }
    }, [data, loading, networkStatus]);

    const location = useLocation<{ autoGenerated?: boolean }>();
    const isAutoGenerated =
        isAutoGenerateEnabled && location.state?.autoGenerated === true;

    useEffect(() => {
        if (isAutoGenerated && !loading) startPolling(5000);
        setEmptyInProgressCount(0);
        return () => {
            stopPolling();
        };
    }, [isAutoGenerated]);

    useEffect(() => {
        if (Boolean(retryBatch) && !loading) {
            startPolling(5000);
            setRetryBatch(0);
            setEmptyInProgressCount(0);
        }
    }, [retryBatch]);

    useEffect(() => {
        if (isAutoGenerateEnabled) {
            const currentFiles: Record<string, InProgressAdjustmentsFile> =
                inProgressAdjustmentsFiles();

            const preExistingFiles: Array<AbacusInProgressAutoAdjustmentFile | null> =
                preExistingAdjustmentFiles();

            const isAnyGenerating =
                autoGeneratedAdjustmentFiles?.some(
                    (file: AbacusInProgressAutoAdjustmentFile | null) =>
                        file?.status === 'generating'
                ) || false;

            const failedToGenerate =
                autoGeneratedAdjustmentFiles?.filter(
                    (file: AbacusInProgressAutoAdjustmentFile | null) =>
                        file?.status === 'failed_to_generate'
                ) || [];

            if (isAnyGenerating || Object.keys(currentFiles).length > 0)
                startPolling(5000);

            const notifiedIds: string[] = [];
            if (failedToGenerate.length > 0) {
                if (!isAnyGenerating) stopPolling();

                client.refetchQueries({
                    include: ['GetStatementPeriodAdjustmentFilesList'],
                });

                failedToGenerate.forEach(
                    (file: AbacusInProgressAutoAdjustmentFile | null) => {
                        const fileId: string | undefined =
                            file?.statementPeriodAdjustmentFile
                                ?.statementPeriodAdjustmentFileId;

                        if (
                            fileId &&
                            currentFiles?.[fileId]?.['status'] === 'generating'
                        ) {
                            toast(
                                fileGenerationFailedMessage(
                                    file?.statementPeriodAdjustmentFile
                                        ?.fileName || ''
                                ),
                                { variant: 'error' }
                            );
                            notifiedIds.push(fileId);
                        }
                    }
                );
            }
            Object.keys(currentFiles)?.forEach((key: string) => {
                const completedFiles =
                    autoGeneratedAdjustmentFiles?.filter(
                        (file: AbacusInProgressAutoAdjustmentFile | null) =>
                            file?.statementPeriodAdjustmentFile
                                ?.statementPeriodAdjustmentFileId ===
                            currentFiles[key]['id']
                    ) || [];

                if (
                    completedFiles.length === 0 &&
                    preExistingFiles.length > 0
                ) {
                    client.refetchQueries({
                        include: ['GetStatementPeriodAdjustmentFilesList'],
                    });
                }
            });
            if (notifiedIds.length > 0) {
                const nextState = { ...currentFiles };

                notifiedIds.forEach(id => {
                    delete nextState[id];
                });

                inProgressAdjustmentsFiles(nextState);
            }

            if (
                autoGeneratedAdjustmentFiles.length === 0 &&
                preExistingFiles.length > 0
            ) {
                setEmptyInProgressCount(count => count + 1);
            }
            if (
                preExistingFiles.length > 0 &&
                autoGeneratedAdjustmentFiles.length === 0
            ) {
                inProgressAdjustmentsFiles({});
                client.refetchQueries({
                    include: ['GetStatementPeriodAdjustmentFilesList'],
                });
            }
        }
    }, [autoGeneratedAdjustmentFiles, loading]);

    useEffect(() => {
        if (emptyInProgressCount > 10) {
            stopPolling();
        }
    }, [emptyInProgressCount]);

    return (
        <div className="Adjustments">
            <PageHeader title="Adjustments">
                {isAutoGenerateEnabled ? (
                    <>
                        <Button
                            className="ml-auto"
                            variant="secondary"
                            onClick={() => history.push(generateAdjustments)}
                        >
                            Auto-Generate Batch
                        </Button>
                        <Button variant="primary" onClick={handleModalOpen}>
                            + Add Adjustments
                        </Button>
                    </>
                ) : (
                    <Button
                        variant="primary"
                        className="ml-auto"
                        onClick={handleModalOpen}
                    >
                        + Add Adjustments
                    </Button>
                )}
            </PageHeader>
            <AdjustmentsList setRetryBatch={setRetryBatch} />
            <AdjustmentsImportModal
                isModalOpen={isModalOpen}
                setIsModalOpen={setIsModalOpen}
            />
        </div>
    );
};

export default Adjustments;
