// tslint:disable:no-console
import * as moment from 'moment';
import * as mongoose from 'mongoose';

import { chevre } from '../../../lib/index';

// const project = { id: String(process.env.PROJECT_ID) };
const STORAGE_PERIOD_IN_DAYS = 30;

// tslint:disable-next-line:max-func-body-length
async function main() {
    await mongoose.connect(<string>process.env.MONGOLAB_URI, { autoIndex: false });

    const taskRepo = await chevre.repository.Task.createInstance(mongoose.connection);
    const transactionRepo = await chevre.repository.Transaction.createInstance(mongoose.connection);

    const cursor = taskRepo.getCursor(
        {
            name: { $eq: chevre.factory.taskName.DeleteTransaction },
            status: { $eq: chevre.factory.taskStatus.Ready }
            // runsAt: {
            //     $gte: moment()
            //         // tslint:disable-next-line:no-magic-numbers
            //         .add(29, 'days')
            //         .toDate(),
            //     $lte: moment()
            //         // tslint:disable-next-line:no-magic-numbers
            //         .add(365, 'days')
            //         .toDate()
            // },
            // _id: { $eq: '6440d8cf9e4983c32ade65de' }
        },
        {
            _id: 1,
            project: 1,
            data: 1,
            status: 1,
            name: 1,
            runsAt: 1
        }
    );
    console.log('tasks found');

    let i = 0;
    let updateCount = 0;
    await cursor.eachAsync(async (doc) => {
        i += 1;
        const deleteTransactionTask: Pick<
            chevre.factory.task.deleteTransaction.ITask,
            'id' | 'project' | 'data' | 'status' | 'name' | 'runsAt'
        > = doc.toObject();

        let placeOrderTransactionId: string | undefined;
        if (deleteTransactionTask.data.object.typeOf === chevre.factory.transactionType.PlaceOrder) {
            if (
                (typeof deleteTransactionTask.data.object.specifyingMethod !== 'string')
                || (deleteTransactionTask.data.object.specifyingMethod === chevre.factory.task.deleteTransaction.SpecifyingMethod.Id)
            ) {
                placeOrderTransactionId = deleteTransactionTask.data.object.id;
            }
        }

        let alreadyMigrated = true;
        let runsAtExpected: moment.Moment | undefined;
        if (typeof placeOrderTransactionId === 'string') {
            console.log(
                'checking transaction...',
                deleteTransactionTask.project.id, deleteTransactionTask.name, deleteTransactionTask.id, deleteTransactionTask.runsAt,
                placeOrderTransactionId
            );
            const placeOrderTransaction = (await transactionRepo.projectFields({
                limit: 1,
                page: 1,
                typeOf: chevre.factory.transactionType.PlaceOrder,
                ids: [placeOrderTransactionId],
                inclusion: ['endDate', 'status']
            })).shift();
            if (placeOrderTransaction !== undefined) {
                const { endDate, status } = placeOrderTransaction;
                runsAtExpected = moment(endDate)
                    // tslint:disable-next-line:no-magic-numbers
                    .add(STORAGE_PERIOD_IN_DAYS, 'days');

                // if (status !== chevre.factory.transactionStatusType.Confirmed) {
                const taskRunsTooLate = moment(deleteTransactionTask.runsAt)
                    .isAfter(runsAtExpected);
                const diff = moment(deleteTransactionTask.runsAt)
                    .diff(moment(endDate));
                console.log('taskRunsTooLate?:', taskRunsTooLate, placeOrderTransactionId, endDate, status, diff.toLocaleString());
                if (taskRunsTooLate) {
                    alreadyMigrated = false;
                }
                // }
            }
        }

        if (alreadyMigrated) {
            console.log(
                'already migrated.',
                deleteTransactionTask.project.id, deleteTransactionTask.name, deleteTransactionTask.id, deleteTransactionTask.runsAt,
                i, updateCount);
        } else {
            console.log(
                'updating...',
                deleteTransactionTask.project.id, deleteTransactionTask.name, deleteTransactionTask.id, deleteTransactionTask.runsAt,
                i, updateCount, runsAtExpected);
            if (runsAtExpected !== undefined) {
                await taskRepo.taskModel.findByIdAndUpdate(
                    deleteTransactionTask.id,
                    {
                        $set: {
                            runsAt: runsAtExpected.toDate()
                        }
                    }
                )
                    .exec();
            }
            updateCount += 1;
            console.log(
                'updated.',
                deleteTransactionTask.project.id, deleteTransactionTask.name, deleteTransactionTask.id, deleteTransactionTask.runsAt,
                i, updateCount, runsAtExpected);
        }
    });

    console.log(i, 'tasks checked');
    console.log(updateCount, 'tasks updated');
}

main()
    .then()
    .catch(console.error);
