import type { FC } from 'react';
import React, { useEffect, useState } from 'react';
import { useApolloClient } from '@apollo/client';
import { BRAND_AWAL } from '@theorchard/constants';
import { Alert, Card, ExpandableContent } from '@theorchard/suite-components';
import { SkeletonLoader } from '@theorchard/suite-components';
import { useFeatureFlag } from '@theorchard/suite-frontend';
import { GlyphIcon } from '@theorchard/suite-icons';
import { filter, isEmpty } from 'lodash-es';
import {
    useCreateVatDocs,
    useUpdateRetryVatDocs,
} from 'src/apollo/mutations/statement-periods';
import { usePaymentEntityVat } from 'src/apollo/queries/payment-entity-vat';
import { useGetVatInvoices } from 'src/apollo/queries/statement-periods';
import { USER_FEATURES, VAT_INVOICES_POLLING_INTERVAL } from 'src/constants';
import { INVOICE_STATUS } from 'src/enum';
import { PaymentEntityStatus } from 'src/types/payment-entity-status-indicator';
import { getPaymentEntityNameById } from 'src/utils/getPaymentEntityNameById';
import Balance from './balance';
import { FailedVatDocsModal } from './failed-vat-docs-modal';
import GenerateVatDocs from './generate-vat-docs';
import PaymentEntityStatusIndicator from './payment-entity-status-indicator';
import { ShowInCustomerAccountingButton } from './show-in-customer-accounting-button';
import { StepIndicator } from './step-indicator';
import VatDocsStatuses from './vat-docs-status';
import type { GetStatementPeriodQuery } from 'src/apollo/queries/statement-periods/__generated__/statement-period';

type AbacusStatementPeriod = NonNullable<
    GetStatementPeriodQuery['abacusStatementPeriod']
>;
type AbacusStatementPaymentEntity = NonNullable<
    AbacusStatementPeriod['paymentEntities'][0]
>;

export const TERM_GENERATION_FAILED =
    'Generation of VAT documents failed. Please try again or contact support.';
export const TERM_RETRY_IN_PROGRESS =
    "Retrying the generation of failed VAT documents may take some time. It's now safe to leave this page and come back later.";
export const TERM_GENERATION_IN_PROGRESS =
    "Generation of VAT documents may take some time. It's now safe to leave this page and come back later.";

enum AlertType {
    GENERATION_FAILED,
    RETRY_IN_PROGRESS,
    GENERATION_IN_PROGRESS,
    NO_VAT,
}
export const TERM_NO_VAT_DATA_ALERT_TITLE = 'No VAT data available yet.';
export const TERM_NO_VAT_DATA_ALERT_TEXT =
    'Once the VAT calculation has completed, it will be possible to generate VAT documents. If you show in accounting now, values may continue to change for the client.';

export interface Props {
    paymentEntity: AbacusStatementPaymentEntity;
    statementPeriod: AbacusStatementPeriod;
}

const CLASS_NAME = 'PaymentEntityItem';

export const PaymentEntityItem: FC<Props> = ({
    paymentEntity,
    statementPeriod,
}) => {
    const [hasVatGenerationError, setHasVatGenerationError] = useState(false);
    // eslint-disable-next-line @typescript-eslint/no-unused-vars
    const [hasRetryGenerationError, setHasRetryGenerationError] =
        useState(false);
    const [isGenerating, setIsGenerating] = useState(false);
    const [isRetrying, setIsRetrying] = useState(false);
    const [isFailedDocsModalOpen, setIsFailedDocsModalOpen] = useState(false);
    const [isExpanded, setIsExpanded] = useState<boolean>(true);
    const [closeBalanceStatus, setCloseBalanceStatus] = useState<
        PaymentEntityStatus | undefined
    >();

    const createVatDocs = useCreateVatDocs();
    const retryVatDocs = useUpdateRetryVatDocs();

    const client = useApolloClient();

    const paymentEntityId =
        paymentEntity?.referencePaymentEntity?.referencePaymentEntityId?.toString() ||
        '';

    const paymentEntityName =
        paymentEntity?.referencePaymentEntity?.paymentEntityName;

    const isAwalClient =
        getPaymentEntityNameById(paymentEntityId, client.cache) === BRAND_AWAL;

    const hasAwalVatDocsTriggerFF = useFeatureFlag(
        USER_FEATURES.ABACUS_AWAL_VAT_DOCS_TRIGGER
    );

    const hasVatDocsTriggerFeature = !isAwalClient || hasAwalVatDocsTriggerFF;

    const { data: paymentEntityVatData, loading: paymentEntityVatDataLoading } =
        usePaymentEntityVat({
            paymentEntityId,
            statementPeriodId: statementPeriod.statementPeriodId,
        });

    const hasVatData = paymentEntityVatData?.vatData ?? false;

    const {
        data: vatInvoices,
        loading: loadingVatInvoices,
        startPolling: startPollingInvoices,
        stopPolling: stopPollingVatInvoices,
    } = useGetVatInvoices({
        paymentEntityId,
        statementPeriodId: statementPeriod.statementPeriodId,
    });
    const invoices = vatInvoices ?? [];
    const hasInvoices = invoices.length > 0;
    const hasInProgressInvoices =
        !loadingVatInvoices &&
        invoices.some(
            invoice =>
                invoice.statementAttachmentStatus == INVOICE_STATUS.IN_PROGRESS
        );
    const hasRetryInvoices =
        !loadingVatInvoices &&
        invoices.some(
            invoice => invoice.statementAttachmentStatus == INVOICE_STATUS.RETRY
        );

    const failedInvoices = filter(invoices, {
        statementAttachmentStatus: INVOICE_STATUS.ERROR,
    });

    const handleGenerateVatDocs = async () => {
        try {
            setHasVatGenerationError(false);
            setIsGenerating(true);

            await createVatDocs({
                variables: {
                    paymentEntityId,
                    statementPeriodId: statementPeriod.statementPeriodId,
                },
            });

            startPollingInvoices(VAT_INVOICES_POLLING_INTERVAL);
        } catch {
            setIsGenerating(false);
            setHasVatGenerationError(true);
            stopPollingVatInvoices();
        }
    };

    const handleRetryVatDocs = async () => {
        try {
            setHasRetryGenerationError(false);
            setIsRetrying(true);
            toggleFailedDocsModal();

            await retryVatDocs({
                variables: {
                    paymentEntityId,
                    statementPeriodId: statementPeriod.statementPeriodId,
                },
            });

            startPollingInvoices(VAT_INVOICES_POLLING_INTERVAL);
        } catch {
            setIsRetrying(false);
            setHasRetryGenerationError(true);
            stopPollingVatInvoices();
        }
    };

    const isVisibleToCustomer = paymentEntity.isVisibleToCustomer;

    const vatDocumentsStatus = () => {
        if (!hasVatDocsTriggerFeature) return PaymentEntityStatus.COMPLETE;
        if (hasRetryGenerationError) {
            return PaymentEntityStatus.BLOCKED;
        }
        if (hasInvoices && !hasInProgressInvoices) {
            return PaymentEntityStatus.COMPLETE;
        } else return PaymentEntityStatus.IN_PROGRESS;
    };

    const statementStatus = isVisibleToCustomer
        ? PaymentEntityStatus.COMPLETE
        : PaymentEntityStatus.IN_PROGRESS;

    const renderVatActions = () => {
        if (!hasVatDocsTriggerFeature) return null;

        if (loadingVatInvoices || paymentEntityVatDataLoading)
            return (
                <SkeletonLoader
                    className={`${CLASS_NAME}-vat-loader`}
                    numberOfItems={1}
                />
            );

        return (
            <Card.Body>
                <div
                    className={`d-flex justify-content-between ${
                        hasInvoices && !hasInProgressInvoices && 'flex-column'
                    }`}
                >
                    <div className="d-flex mr-10 align-items-center">
                        <StepIndicator
                            variant={
                                hasInvoices && !hasInProgressInvoices
                                    ? 'success'
                                    : 'neutral'
                            }
                            glyphIconName="check"
                        />
                        <div className="step-name">VAT Documents</div>
                    </div>
                    {hasInvoices && !hasInProgressInvoices ? (
                        <VatDocsStatuses
                            hasRetryGenerationError={hasRetryGenerationError}
                            invoices={invoices}
                            toggleFailedDocsModal={toggleFailedDocsModal}
                            isRetrying={isRetrying}
                        />
                    ) : (
                        <GenerateVatDocs
                            statementPeriod={statementPeriod}
                            paymentEntity={paymentEntity.referencePaymentEntity}
                            onGenerateVatDocs={handleGenerateVatDocs}
                            hasVatData={hasVatData}
                            hasInProgressInvoices={hasInProgressInvoices}
                            isGenerating={isGenerating}
                        />
                    )}
                </div>
                {!hasVatData && renderAlert(AlertType.NO_VAT)}
                {hasVatGenerationError &&
                    renderAlert(AlertType.GENERATION_FAILED)}
                {isRetrying && renderAlert(AlertType.RETRY_IN_PROGRESS)}
                {isGenerating && renderAlert(AlertType.GENERATION_IN_PROGRESS)}
            </Card.Body>
        );
    };

    const renderAlert = (alert: AlertType) => {
        if (
            !hasVatDocsTriggerFeature ||
            loadingVatInvoices ||
            paymentEntityVatDataLoading
        )
            return null;

        switch (alert) {
            case AlertType.GENERATION_FAILED:
                return (
                    <Alert
                        variant="error"
                        text={TERM_GENERATION_FAILED}
                        className={`${CLASS_NAME}-alert`}
                    />
                );
            case AlertType.RETRY_IN_PROGRESS:
                return (
                    <Alert
                        variant="information"
                        text={TERM_RETRY_IN_PROGRESS}
                        className={`${CLASS_NAME}-alert`}
                    />
                );
            case AlertType.GENERATION_IN_PROGRESS:
                return (
                    <Alert
                        variant="information"
                        text={TERM_GENERATION_IN_PROGRESS}
                        className={`${CLASS_NAME}-alert`}
                    />
                );
            case AlertType.NO_VAT:
                return (
                    <Alert
                        variant="warn"
                        title={TERM_NO_VAT_DATA_ALERT_TITLE}
                        text={TERM_NO_VAT_DATA_ALERT_TEXT}
                        className={`${CLASS_NAME}-alert`}
                    />
                );
        }
    };

    useEffect(() => {
        if (isEmpty(invoices)) return;

        setIsRetrying(hasRetryInvoices);
        setIsGenerating(hasInProgressInvoices);

        if (hasInProgressInvoices || hasRetryInvoices)
            startPollingInvoices(VAT_INVOICES_POLLING_INTERVAL);

        return () => {
            stopPollingVatInvoices();
        };
    }, [invoices, hasInProgressInvoices, hasRetryInvoices]);

    const toggleFailedDocsModal = () => {
        setIsFailedDocsModalOpen(!isFailedDocsModalOpen);
    };

    return (
        <div
            className={`${CLASS_NAME}-redesign`}
            data-testid={`payment-entity-${paymentEntity.referencePaymentEntity.referencePaymentEntityId}`}
        >
            <Card>
                <div
                    className="d-flex justify-content-between pb-1"
                    role="button"
                    tabIndex={0}
                    onClick={() => setIsExpanded(!isExpanded)}
                    onKeyDown={e => {
                        if (e.key === 'Enter' || e.key === ' ')
                            setIsExpanded(!isExpanded);
                    }}
                >
                    <div className="d-flex align-items-start">
                        <h3>{paymentEntityName}</h3>
                        <PaymentEntityStatusIndicator
                            closeBalanceStatus={closeBalanceStatus}
                            statementStatus={statementStatus}
                            vatDocumentsStatus={vatDocumentsStatus()}
                        />
                    </div>
                    <GlyphIcon
                        name={isExpanded ? 'chevronUp' : 'chevronDown'}
                        size={16}
                    />
                </div>
                <ExpandableContent
                    expanded={isExpanded}
                    onToggle={setIsExpanded}
                >
                    <Balance
                        paymentEntity={paymentEntity}
                        statementPeriod={statementPeriod}
                        setCloseBalanceStatus={setCloseBalanceStatus}
                    />
                    {renderVatActions()}
                    <Card.Body>
                        <div
                            className={`d-flex justify-content-between ${
                                isVisibleToCustomer && 'flex-column'
                            }`}
                        >
                            <div className="d-flex align-items-center">
                                <StepIndicator
                                    variant={
                                        isVisibleToCustomer
                                            ? 'success'
                                            : 'neutral'
                                    }
                                    glyphIconName="check"
                                />
                                <div className="step-name">Statement</div>
                            </div>
                            <ShowInCustomerAccountingButton
                                statementPeriod={statementPeriod}
                                paymentEntity={paymentEntity}
                            />
                        </div>
                    </Card.Body>
                </ExpandableContent>
            </Card>
            <FailedVatDocsModal
                statementPeriodName={statementPeriod.statementPeriodName}
                paymentEntityName={paymentEntityName || ''}
                failedDocs={failedInvoices}
                isOpen={isFailedDocsModalOpen}
                toggleModal={toggleFailedDocsModal}
                onRetryVatDocs={handleRetryVatDocs}
            />
        </div>
    );
};
