import { ApolloClient } from '@apollo/client';
import { getContract } from 'src/apollo/queries/contract';
import {
    BulkEditEntryBase,
    BulkSchema,
    runInBatches,
} from './common-bulk-edit-schema';
import type { GridTableColumnDefinition } from '@theorchard/suite-components';
import React from 'react';
import { Link } from 'react-router-dom';
import { getContractDetail } from 'src/urls/frontend-royalties';
import terminateContract from 'src/apollo/mutations/contract/terminate-contract.gql';
import { convertXlsxCellToDateString } from 'src/components/contract-bulk-edit/common/edit-schema/utils';
import {
    GET_CONTRACT_MAX_PARALLEL,
    UPDATE_CONTRACT_TERMINATE_MAX_PARALLEL,
} from 'src/components/contract-bulk-edit/common/edit-schema/constants';

const CONTRACT_TERMINATE_TABLE_HEADERS: GridTableColumnDefinition<ContractTerminateBulkEditEntry>[] =
    [
        {
            name: 'contractId',
            title: 'Contract Id',
        },
        {
            name: 'contractName',
            title: 'Contract Name',
            Cell: ({ data: { contractId, contractName } }: any) => (
                <div>
                    {contractName ? (
                        <Link
                            key={contractId}
                            to={getContractDetail(contractId)}
                        >
                            {contractName}
                        </Link>
                    ) : (
                        '-'
                    )}
                </div>
            ),
        },
        {
            name: 'currentLifecycleStatus',
            title: 'Current Status',
        },
        {
            name: 'terminationEffective',
            title: 'Termination Effective',
        },
        {
            name: 'terminationNoticeReceived',
            title: 'Termination Notice Received',
        },
    ];

export interface ContractTerminateBulkEditEntry extends BulkEditEntryBase {
    id: string;
    contractId: string;
    contractName: string | undefined | null;
    currentLifecycleStatus: string | undefined | null;

    terminationEffective: string | undefined | null;
    terminationNoticeReceived: string | undefined | null;
}

export const contractTerminateSchema: BulkSchema<ContractTerminateBulkEditEntry> =
    {
        id: 'contractTerminate',
        displayName: 'Contract Terminate',
        columns: CONTRACT_TERMINATE_TABLE_HEADERS,
        expectedFileColumns: [
            {
                name: 'contract_id',
                description: 'Contract ID to terminate',
            },
            {
                name: 'termination_effective',
                description: 'Termination date (YYYY-MM-DD)',
            },
            {
                name: 'termination_notice_received',
                description:
                    'Termination notice received date (YYYY-MM-DD). Optional.',
            },
        ],
        async toEntries(apolloClient: ApolloClient<object>, rows: any[]) {
            const mapEntry = async (
                entry: any
            ): Promise<ContractTerminateBulkEditEntry> => {
                const contractId: string = entry['contract_id'];
                const terminationEffective: string | null =
                    convertXlsxCellToDateString(entry['termination_effective']);
                const terminationNoticeReceived: string | null =
                    convertXlsxCellToDateString(
                        entry['termination_notice_received']
                    );

                const { data: contractData } = await apolloClient.query({
                    query: getContract,
                    variables: {
                        contractId,
                        groupAdmin: 'PRESENTATIONAL',
                    },
                    fetchPolicy: 'network-only',
                });

                if (!contractData.abacusContract) {
                    return {
                        id: contractId,
                        contractId,
                        contractName: undefined,
                        currentLifecycleStatus: undefined,
                        terminationEffective,
                        terminationNoticeReceived,
                    };
                }

                return {
                    id: contractId,
                    contractId,
                    contractName: contractData.abacusContract.contractName,
                    currentLifecycleStatus:
                        contractData.abacusContract.lifecycle?.lifecycleStatus,
                    terminationEffective,
                    terminationNoticeReceived,
                };
            };

            return await runInBatches(
                rows,
                GET_CONTRACT_MAX_PARALLEL,
                mapEntry
            );
        },
        async apply(apolloClient, entries, onSuccess, onFail) {
            await runInBatches(
                entries,
                UPDATE_CONTRACT_TERMINATE_MAX_PARALLEL,
                async entry => {
                    if (!entry.contractName) {
                        onFail(
                            entry,
                            new Error('No contract to terminate.'),
                            'No contract to terminate.'
                        );
                        return;
                    }

                    const variables: any = {
                        contractId: entry.contractId,
                        terminationEffective: entry.terminationEffective,
                        terminationNoticeReceived:
                            entry.terminationNoticeReceived || undefined,
                    };

                    try {
                        await apolloClient.mutate({
                            mutation: terminateContract,
                            variables,
                        });
                        onSuccess(entry);
                    } catch (error) {
                        onFail(entry, error, 'Error terminating contract.');
                    }
                }
            );
        },
    };
