// tslint:disable:no-console no-magic-numbers
import * as moment from 'moment';
import * as mongoose from 'mongoose';
import * as redis from 'redis';
import * as util from 'util';

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

// const project = { id: String(process.env.PROJECT_ID) };
const { BACKLOG_ISSUE_KEY, BACKLOG_API_KEY, BACKLOG_SPACE_KEY } = process.env;
const BACKLOG_NOTIFY_URL = `https://${BACKLOG_SPACE_KEY}.backlog.jp/api/v2/issues/${BACKLOG_ISSUE_KEY}/comments?apiKey=${BACKLOG_API_KEY}`;

const client = redis.createClient<redis.RedisDefaultModules, Record<string, never>, Record<string, never>>({
    socket: {
        port: Number(<string>process.env.REDIS_PORT),
        host: <string>process.env.REDIS_HOST
    },
    password: <string>process.env.REDIS_KEY,
    name: 'checkRedisKeyCount'
})
    .on('error', (err) => {
        // eslint-disable-next-line no-console
        console.error('createDefaultRedisClient: client onError:', err);
        // reject(err);
    });
client.connect();
mongoose.connect(<string>process.env.MONGOLAB_URI, { autoIndex: false });

function countRedisKeyByProject(params: {
    project: { id: string };
    now: Date;
}) {
    return async (repos: {
        event: chevre.repository.Event;
        stockHolder: chevre.repository.StockHolder;
    }) => {
        const cursor = repos.event.getCursor(
            {
                'project.id': {
                    $eq: params.project.id
                    // $in: useMongoAsStockHolderProjects
                },
                // startDate: {
                //     $gte: params.now
                // },
                endDate: {
                    $gte: params.now
                },
                typeOf: { $eq: chevre.factory.eventType.ScreeningEvent }
                // _id: { $eq: 'blyk9q24f' }
            },
            {
                _id: 1,
                // offers: 1,
                startDate: 1,
                project: 1,
                typeOf: 1
            }
        );
        console.log('events found');

        let i = 0;
        let redisKeyCount = 0;
        const eventsWithRedis: string[] = [];
        await cursor.eachAsync(async (doc) => {
            i += 1;
            const event: Pick<
                chevre.factory.event.screeningEvent.IEvent,
                'id' | 'startDate' | 'project' | 'typeOf'
            > = doc.toObject();

            console.log('redisKeyExists?', event.project.id, event.typeOf, event.id, event.startDate, i);
            const redisKeyExists = await repos.stockHolder.redisKeyExists({
                eventId: event.id,
                startDate: event.startDate
            });
            console.log('redisKeyExists:', redisKeyExists, event.project.id, event.typeOf, event.id, event.startDate, i);

            if (redisKeyExists) {
                redisKeyCount += 1;
                eventsWithRedis.push(event.id);
            }
        });

        console.log(i, 'events checked');
        console.log(redisKeyCount, 'redisKeys found');

        return { checkedCount: i, redisKeyCount, eventsWithRedis };
    };
}

// tslint:disable-next-line:max-func-body-length
async function main() {
    const eventRepo = await chevre.repository.Event.createInstance(mongoose.connection);
    const projectRepo = await chevre.repository.Project.createInstance(mongoose.connection);
    const settingRepo = await chevre.repository.Setting.createInstance(mongoose.connection);
    const stockHolderRepo = await chevre.repository.StockHolder.createInstance(
        client,
        mongoose.connection
    );

    const setting = await settingRepo.findOne(
        { project: { id: { $eq: '*' } } },
        ['useMongoAsStockHolderProjects', 'useMongoAsStockHolder']
    );
    const useMongoAsStockHolder = setting?.useMongoAsStockHolder === true;
    let useMongoAsStockHolderProjects =
        (Array.isArray(setting?.useMongoAsStockHolderProjects)) ? setting?.useMongoAsStockHolderProjects : [];
    if (useMongoAsStockHolder) {
        // 全プロジェクト
        useMongoAsStockHolderProjects = (await projectRepo.projectFields(
            {
                // id: { $eq: 'xxx' }
            },
            ['id']
        )).map(({ id }) => id);
    }

    useMongoAsStockHolderProjects = useMongoAsStockHolderProjects.filter((id) => id.slice(0, 6) !== 'sskts-');

    const results: {
        project: { id: string };
        checkedCount: number;
        redisKeyCount: number;
    }[] = [];

    const now = moment()
        .add(0, 'days')
        .toDate();
    for (const projectId of useMongoAsStockHolderProjects) {
        const { checkedCount, redisKeyCount } = await countRedisKeyByProject({
            project: { id: projectId },
            now
        })({
            event: eventRepo,
            stockHolder: stockHolderRepo
        });
        results.push({
            project: { id: projectId },
            checkedCount,
            redisKeyCount
        });
        // console.log(eventsWithRedis);
    }

    const header = util.format(
        '| %s | %s | %s | %s |\n| %s | %s | %s | %s |',
        `project                                    `.slice(0, 40),
        `now                              `.slice(0, 24),
        `checkedCount                              `.slice(0, 24),
        `redisKeyCount                              `.slice(0, 24),
        `----------------------------------------                                    `.slice(0, 40),
        `------------------------                              `.slice(0, 24),
        `------------------------                              `.slice(0, 24),
        `------------------------                              `.slice(0, 24)
    );

    const text = util.format(
        '%s\n%s',
        header,
        results.map((result) => {
            return util.format(
                '| %s | %s | %s | %s |',
                `${result.project.id}                                    `.slice(0, 40),
                `${now.toISOString()}                              `.slice(0, 24),
                `${result.checkedCount}                              `.slice(0, 24),
                `${result.redisKeyCount}                              `.slice(0, 24)
            );
        })
            .join('\n')
    );
    console.log(text);

    // backlogへ通知
    if (typeof BACKLOG_API_KEY === 'string') {
        console.log('notifying on backlog...');
        await fetch(
            BACKLOG_NOTIFY_URL,
            {
                method: 'POST',
                headers: new Headers({ 'Content-Type': 'application/json' }),
                body: JSON.stringify({
                    content: text,
                    notifiedUserId: []
                    // notifiedUserId: users.map((user) => user.id)
                })
            }
        );
        console.log('posted to backlog.');
    }
}

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