import type { PropsWithChildren } from 'react';
import React from 'react';
import {
    Button,
    LoadingSpinner,
    Tooltip,
    Pill,
} from '@theorchard/suite-components';
import { GlyphIcon } from '@theorchard/suite-icons';
import { Link } from 'react-router-dom';
import {
    AUTO_GENERATE_BATCH_LINK_TOOLTIP_MSG,
    ADJUSTMENT_FILE_STATUSES_MAP,
    NO_AUTO_FLOWTHROUGH_ADJUSTMENTS_TITLE,
    FAILED_AUTO_FLOWTHROUGH_ADJUSTMENTS_TITLE,
} from 'src/apollo/type-constants/adjustment';
import { getAdjustmentsBatchPage } from 'src/urls/frontend-royalties';
import { formatNumberWithCommas } from 'src/utils/number-helper';
import type { GridTableColumnDefinition } from '@theorchard/suite-components';
import type { CellProps } from '@theorchard/suite-components/dist/esm/src/components/table/base/types';
import {
    ABACUS_ACTION_STATUSES,
    EMPTY_CHAR,
} from '@theorchard/accounting-apps-shared';
import { GetStatementPeriodAdjustmentFilesListQuery } from 'src/apollo/queries/adjustment/__generated__/get-statement-period-adjustments-files-list';

type AbacusEvent = NonNullable<
    NonNullable<
        GetStatementPeriodAdjustmentFilesListQuery['abacusStatementPeriodAdjustmentFilesList']
    >['items'][number]['abacusEvents']
>[number];

const renderWarnPopoverContent = (
    deleteBatch: (fileId: string) => void,
    fileId: string
) => (
    <div className="Alert Alert-warn card">
        <div className="Alert-body card-body">
            <div className="Alert-content content-top">
                <div className="Alert-icons">
                    <GlyphIcon name="warning" size={24} />
                </div>
                <div className="Alert-elements">
                    <h5 className="Alert-title">
                        {NO_AUTO_FLOWTHROUGH_ADJUSTMENTS_TITLE}
                    </h5>
                    <div className="Alert-text">
                        The process completed successfully, but no <br />
                        accounts matched your selected criteria. Try <br />
                        adjusting your filters and run the generation again.
                    </div>
                </div>
            </div>
            <div className="content-top ml-auto">
                <Button variant="primary" onClick={() => deleteBatch(fileId)}>
                    Delete Batch
                </Button>
            </div>
        </div>
    </div>
);

const renderFailedPopoverContent = (
    abacusEvents: AbacusEvent[] | null,
    fileName: string,
    disableRetryBatch: number,
    fileId: string,
    deleteBatch: (fileId: string) => void,
    retryBatch: (fileId: string, fileName: string) => void
) => {
    const eventsCount =
        abacusEvents?.filter(
            (abacusEvent: AbacusEvent | null) =>
                abacusEvent?.eventName === 'generate_flowthrough_adjustments'
        ) || [];
    return (
        <div className="Alert Alert-error card">
            <div className="Alert-body card-body">
                <div className="Alert-content content-top">
                    <div className="Alert-icons">
                        <GlyphIcon name="warning" size={24} />
                    </div>
                    <div className="Alert-elements">
                        <h5 className="Alert-title">
                            {FAILED_AUTO_FLOWTHROUGH_ADJUSTMENTS_TITLE}
                        </h5>
                        {eventsCount?.length <= 1 ? (
                            <div className="Alert-text">
                                Due to a system error, the {fileName}
                                adjustment batch <br /> has not been generated.
                                Please delete or retry the generation
                            </div>
                        ) : (
                            <div className="Alert-text">
                                Due to a system error, the {fileName}
                                adjustment batch <br /> failed again. Please
                                contact support.
                            </div>
                        )}
                    </div>
                </div>
                <div className="content-top ml-auto">
                    <Button
                        className="AdjustmentsListTable-delete-batch"
                        variant="primary"
                        onClick={() => deleteBatch(fileId)}
                    >
                        Delete Batch
                    </Button>
                    {eventsCount?.length <= 1 ? (
                        <Button onClick={() => retryBatch(fileId, fileName)}>
                            {disableRetryBatch === parseInt(fileId, 10)
                                ? `Regenerating Batch`
                                : `Retry Generation`}
                        </Button>
                    ) : (
                        <Button variant="tertiary">Contact Support</Button>
                    )}
                </div>
            </div>
        </div>
    );
};

const showBatchIdStatus = (
    abacusEvents: AbacusEvent[] | null,
    status: string,
    statementPeriodAdjustmentFileId: string,
    fileName: string,
    disableRetryBatch: number,
    deleteBatch: (fileId: string) => void,
    retryBatch: (fileId: string, fileName: string) => void
) => {
    if (status === 'no_records')
        return (
            <>
                <span
                    className="AdjustmentsListTable-disabled-batchId"
                    data-testid="disabled-batchId-link"
                >
                    {statementPeriodAdjustmentFileId}
                </span>
                <Pill
                    iconCategory="glyph"
                    iconName="warning"
                    className="AdjustmentsListTable-warning-error-tooltip"
                    popoverOptions={{
                        id: 'noRecordsPopover',
                        content: (
                            <span>
                                {renderWarnPopoverContent(
                                    deleteBatch,
                                    statementPeriodAdjustmentFileId
                                )}
                            </span>
                        ),
                    }}
                />
            </>
        );

    if (status === 'failed_to_generate')
        return (
            <>
                <span
                    className="AdjustmentsListTable-disabled-batchId"
                    data-testid="disabled-batchId-link"
                >
                    {statementPeriodAdjustmentFileId}
                </span>
                <Pill
                    iconCategory="glyph"
                    iconName="warning"
                    className="AdjustmentsListTable-error-tooltip"
                    popoverOptions={{
                        id: 'failedToGeneratePopover',
                        content: (
                            <span>
                                {renderFailedPopoverContent(
                                    abacusEvents,
                                    fileName,
                                    disableRetryBatch,
                                    statementPeriodAdjustmentFileId,
                                    deleteBatch,
                                    retryBatch
                                )}
                            </span>
                        ),
                    }}
                />
            </>
        );

    return (
        <Tooltip
            id="generateTooltip"
            placement="top"
            message={AUTO_GENERATE_BATCH_LINK_TOOLTIP_MSG}
        >
            <span
                className="AdjustmentsListTable-disabled-batchId"
                data-testid="disabled-batchId-link"
            >
                {statementPeriodAdjustmentFileId}
            </span>
        </Tooltip>
    );
};
const AdjustmentsListTableColumns = (
    isAutoGenerateEnabled: boolean,
    disableRetryBatch: number,
    deleteBatch: (file: string) => void,
    retryBatch: (fileId: string, fileName: string) => void
) => {
    const ADJUSTMENTS_LIST_COLUMNS: GridTableColumnDefinition<unknown>[] = [
        {
            name: 'status',
            title: 'Status',
            maxWidth: '1fr',
            minWidth: 'min-content',
            sortable: true,
            fixed: true,
            Cell: ({
                data: { actionStates, status },
            }: PropsWithChildren<CellProps<any>>) => {
                const hasErrorStatus = actionStates.some(
                    (actionState: { actionStatus: string }) =>
                        actionState.actionStatus ===
                        ABACUS_ACTION_STATUSES.ERROR
                );

                const inRunning =
                    actionStates.filter(
                        (actionState: {
                            actionName: string;
                            actionStatus: string;
                        }) =>
                            actionState.actionStatus ===
                                ABACUS_ACTION_STATUSES.INIT &&
                            actionState.actionName === 'upload_file'
                    ) || [];

                return (
                    <>
                        {isAutoGenerateEnabled &&
                        (status === 'generating' ||
                            status === null ||
                            inRunning.length > 0) ? (
                            <LoadingSpinner show size={12} />
                        ) : (
                            <span
                                className={
                                    hasErrorStatus
                                        ? ABACUS_ACTION_STATUSES.ERROR
                                        : status
                                }
                            >
                                <GlyphIcon name="dot" size={16} />
                            </span>
                        )}
                        <span className="status">
                            {hasErrorStatus && status !== 'failed_to_generate'
                                ? ADJUSTMENT_FILE_STATUSES_MAP.error
                                : isAutoGenerateEnabled &&
                                    (status === null || inRunning.length > 0)
                                  ? 'Generating'
                                  : ADJUSTMENT_FILE_STATUSES_MAP[status]}
                        </span>
                    </>
                );
            },
        },
        {
            name: 'validRowCount',
            title: 'Total Adjustments & Expenses',
            maxWidth: '185px',
            minWidth: '185px',
            Cell: ({
                data: { validRowCount, status },
            }: PropsWithChildren<CellProps<any>>) => (
                <>
                    {isAutoGenerateEnabled &&
                    ['generating', 'failed_to_generate', null].includes(status)
                        ? '-'
                        : isAutoGenerateEnabled && status === 'no_records'
                          ? 0
                          : validRowCount}
                </>
            ),
        },
        {
            name: 'statementPeriodAdjustmentFileId',
            title: 'Batch Id',
            maxWidth: '100px',
            minWidth: '100px',
            Cell: ({
                data: {
                    abacusEvents,
                    actionStates,
                    fileName,
                    statementPeriodAdjustmentFileId,
                    status,
                },
            }: PropsWithChildren<CellProps<any>>) => {
                const inRunning = actionStates.filter(
                    (actionState: {
                        actionName: string;
                        actionStatus: string;
                    }) =>
                        actionState.actionStatus ===
                            ABACUS_ACTION_STATUSES.INIT &&
                        actionState.actionName === 'upload_file'
                );
                return (
                    <>
                        {(isAutoGenerateEnabled &&
                            [
                                'generating',
                                'failed_to_generate',
                                'no_records',
                            ].includes(status)) ||
                        status == null ||
                        inRunning.length > 0 ? (
                            showBatchIdStatus(
                                abacusEvents,
                                status || 'generating',
                                statementPeriodAdjustmentFileId,
                                fileName,
                                disableRetryBatch,
                                deleteBatch,
                                retryBatch
                            )
                        ) : (
                            <Link
                                key={statementPeriodAdjustmentFileId}
                                to={getAdjustmentsBatchPage(
                                    statementPeriodAdjustmentFileId
                                )}
                                data-testid={`batchPageLink${statementPeriodAdjustmentFileId}`}
                                aria-disabled="true"
                            >
                                {statementPeriodAdjustmentFileId}
                            </Link>
                        )}
                    </>
                );
            },
        },
        {
            name: 'fileName',
            title: 'File Name',
            maxWidth: '300px',
            minWidth: '300px',
            Cell: ({
                data: { fileName },
            }: PropsWithChildren<CellProps<any>>) => (
                <>
                    <div
                        style={{
                            whiteSpace: 'pre-wrap',
                        }}
                    >
                        {fileName}
                    </div>
                </>
            ),
        },
        {
            name: 'statementPeriod.statementPeriodName',
            title: 'Statement Period',
            maxWidth: '1fr',
            minWidth: 'min-content',
            Cell: ({
                data: {
                    statementPeriod: { statementPeriodName },
                },
            }: PropsWithChildren<CellProps<any>>) => <>{statementPeriodName}</>,
        },
        {
            name: 'createdAt',
            title: 'Date Added',
            maxWidth: '1fr',
            minWidth: 'min-content',
            sortable: true,
            Cell: ({
                data: { createdAt },
            }: PropsWithChildren<CellProps<any>>) => <>{createdAt}</>,
        },
        {
            name: 'createdBy',
            title: 'Added By',
            maxWidth: '1fr',
            minWidth: 'min-content',
            Cell: ({
                data: { createdBy, createdByIdentity },
            }: PropsWithChildren<CellProps<any>>) => (
                <>{createdByIdentity ? createdByIdentity.name : createdBy}</>
            ),
        },
        {
            name: 'dateApproved',
            title: 'Date Approved',
            maxWidth: '1fr',
            minWidth: 'min-content',
            sortable: true,
            Cell: ({
                data: { dateApproved },
            }: PropsWithChildren<CellProps<any>>) => (
                <>{dateApproved ? dateApproved : EMPTY_CHAR}</>
            ),
        },
        {
            name: 'approvedBy',
            title: 'Approved By',
            maxWidth: '1fr',
            minWidth: 'min-content',
            Cell: ({
                data: { approvedBy, approvedByIdentity },
            }: PropsWithChildren<CellProps<any>>) => (
                <>
                    {approvedByIdentity
                        ? approvedByIdentity.name
                        : approvedBy
                          ? approvedBy
                          : EMPTY_CHAR}
                </>
            ),
        },
        {
            name: 'dateApplied',
            title: 'Date Applied',
            maxWidth: '1fr',
            minWidth: 'min-content',
            Cell: ({
                data: { dateApplied },
            }: PropsWithChildren<CellProps<any>>) => (
                <>{dateApplied ? dateApplied : EMPTY_CHAR}</>
            ),
        },
        {
            name: 'totalRoundedAmountMulticurrency',
            title: 'Total Amount (MUL)',
            maxWidth: '1fr',
            minWidth: 'min-content',
            align: 'right',
            Cell: ({
                data: { totalRoundedAmountMulticurrency },
            }: PropsWithChildren<CellProps<any>>) => (
                <>
                    {formatNumberWithCommas(
                        totalRoundedAmountMulticurrency,
                        true
                    )}
                </>
            ),
        },
        ...(isAutoGenerateEnabled
            ? [
                  {
                      name: 'autoGenerated',
                      title: 'Auto-Generated',
                      maxWidth: '1fr',
                      minWidth: 'min-content',
                      Cell: ({
                          data: { batchType },
                      }: PropsWithChildren<CellProps<any>>) => (
                          <>{batchType === 'auto' ? 'Yes' : 'No'}</>
                      ),
                  },
              ]
            : []),
    ];

    return ADJUSTMENTS_LIST_COLUMNS;
};

export default AdjustmentsListTableColumns;
