import express from 'express';
import passport from 'passport';
import { MongoShelf, MongoShelfWord } from '../models/shelf';
import { DB_NAME, getDatabaseClient } from '../db-utils';
import { MongoCategory } from '../models/category';
import { MongoUser } from '../models/user';
import { ObjectId } from 'bson';
import { RecollectionHistory } from '../models/recollection-history';

export const recollectionRoutes = express.Router();

export const jwtAuthentication = passport.authenticate('jwt', { session: false });

recollectionRoutes.get('/questions/', jwtAuthentication, async (request, response) => {
    const user: MongoUser = (request.user as any);

    const shelfCollection = getDatabaseClient().db(DB_NAME).collection<MongoShelf>('shelves');
    const categoryCollection = getDatabaseClient().db(DB_NAME).collection<MongoCategory>('categories');

    if (!user.categories || user.categories.length === 0) {
        response.status(400);
        response.send("No categories found");
        return;
    }

    let categoryIds: Array<ObjectId> = user.categories.map(id => new ObjectId(id));

    const categoryDetails = await categoryCollection.find({
        _id: { $in : categoryIds }
    }).toArray();
    
    
    const shelfIds: Array<ObjectId> = [];

    for (let i = 0; i < categoryDetails.length; i += 1) {
        if (categoryDetails[i].shelves) {

            for (let j = 0; j < categoryDetails[i].shelves.length; j += 1) {
                shelfIds.push(new ObjectId(categoryDetails[i].shelves[j]));
            }
        }
    }

    const shelfDetails: any = await shelfCollection.find({
        _id: { $in : shelfIds }
    }).toArray();

    if (!shelfDetails || shelfDetails.length === 0) {
        response.status(400);
        response.send("No shelves found");
        return;
    }

    interface WordWithShelfId extends MongoShelfWord {
        shelfId: string
    }

    const allWords: Array<WordWithShelfId> = [];

    for (let i = 0; i < shelfDetails.length; i += 1) {
        if (shelfDetails[i].words) {
            for (let j = 0; j < shelfDetails[i].words.length; j += 1) {
                allWords.push({
                    ...shelfDetails[i].words[j],
                    shelfId: shelfDetails[i]._id
                });
            }
        }
    }

    if (allWords.length === 0) {
        response.status(400);
        response.send("No words found");
        return;
    }

    const recollectionWords: Array<MongoShelfWord> = [];
    
    allWords.forEach(word => {
        return new Date(word.nextRevisionDateTime) < new Date() ? recollectionWords.push(word): null;
    });

    response.status(200);
    response.json(recollectionWords);
    

    return;
});


recollectionRoutes.post('/success/', jwtAuthentication, async (request, response) => {
    const shelfCollection = getDatabaseClient().db(DB_NAME).collection<MongoShelf>('shelves');
    const recollectionHistoryCollection = getDatabaseClient().db(DB_NAME).collection<RecollectionHistory>('recollection-history');


    if (!request.body.shelfId || !request.body.wordId) {
        response.status(400);
        response.send("Missing params shelfId or wordId");
        return;
    }
    

    const matchedShelf = await shelfCollection.findOne({
        _id: new ObjectId(request.body.shelfId)
    });

    if (matchedShelf) {
        const matchedWord = matchedShelf.words.find((word) => {
            return word.word === request.body.wordId;
        });
    
        matchedWord.spaceBetweenRecall *= 2;
        let now = new Date();
        matchedWord.nextRevisionDateTime = new Date(now.setDate(now.getDate() + matchedWord.spaceBetweenRecall));
    
        response.status(200);
        response.send(matchedWord);
    } else {
        response.status(400);
        response.send("Unmatched Shelf");
    }

    return;
});