const ObjectId = require('mongodb').ObjectID

const { getDB } = require('../../../utils/mongo')
const dishData = require('./data/dishdata.json')
const tabsData = require('./data/tabs.json')
const { getResponse, _idToIdArray, _idToId } = require('./utils/common')

const DISH_COLLECTION = 'default_dishes'
const TAB_COLLECTION = 'default_tabs'
const USER_COLLECTION = 'users'

const _idRemove = (data) => {
    const { _id, ...rest } = data

    return {
        _id: undefined,
        ...rest,
    }
}

let db = null

const connect = async () => {
    db = await getDB('dish')
}

const init = async () => {
    await connect()
    const dishesCollection = db.collection(DISH_COLLECTION)
    const findDish = await dishesCollection.find({
    }).toArray()
    if (findDish.length === 0) {
        await dishesCollection.insertMany(dishData)
    }
    const tabsCollection = db.collection(TAB_COLLECTION)
    const findTabs = await tabsCollection.find({
    }).toArray()
    if (findTabs.length === 0) {
        await tabsCollection.insertMany(tabsData)
    }
    const usersCollection = db.collection(USER_COLLECTION)
}

init()

const getDish = async () => {
    if (db === null) throw new Error('no db connection')
    try {
        const dishesCollection = db.collection(DISH_COLLECTION)
        const defaultDishes = await dishesCollection.find({}).toArray()
        return _idToIdArray(defaultDishes)
    } catch (e) {
        throw new Error(e)
    }
}

const getTabs = async () => {
    if (db === null) throw new Error('no db connection')
    try {
        const tabsCollection = db.collection(TAB_COLLECTION)
        const defaultTabs = await tabsCollection.find({}).toArray()
        return _idToIdArray(defaultTabs)
    } catch (e) {
        throw new Error(e)
    }
}

const updateTab = async (id, timestampsNew) => {
    if (db === null) throw new Error('no db connection')
    try {
        const tabsCollection = db.collection(TAB_COLLECTION)
        const findData = await tabsCollection.findOne({
            _id: new ObjectId(id),
        })
        if (!findData) throw new Error('Tabs is  not exist')
        const filter = {
            _id: new ObjectId(id),
        }
        const options = {
            upsert: false,
        }
        const updateDoc = {
            $set: {
                timeStamps: timestampsNew,
            },
        }
        const result = await tabsCollection.updateOne(filter, updateDoc, options)
        return _idToId(result)
    } catch (e) {
        throw new Error(e)
    }
}

const getUsers = async () => {
    if (db === null) throw new Error('no db connection')
    try {
        const usersCollection = db.collection(USER_COLLECTION)
        const users = await usersCollection.find({
        }).project({
            _id: 0,
        }).toArray()
        return _idToIdArray(users)
    } catch (e) {
        throw new Error(e)
    }
}

const getUserByEmail = async ({ email }) => {
    if (db === null) throw new Error('no db connection')
    try {
        const usersCollection = db.collection(USER_COLLECTION)
        const user = await usersCollection.findOne(
            {
                email,
            },
            {
                projection:
                {
                    _id: 0,
                },
            },
        )
        return user
    } catch (e) {
        throw new Error(e)
    }
}

const addUser = async ({ email, hash }) => {
    if (db === null) throw new Error('no db connection')
    try {
        const usersCollection = db.collection(USER_COLLECTION)
        const user = await usersCollection.findOne(
            {
                email,
            },
        )
        if (user) throw new Error('User is exist')
        const insertData = await usersCollection.insertOne(
            {
                email,
                hash,
            },
        )
        const { insertedCount, ops } = insertData
        if (insertedCount) {
            return _idRemove(ops[0])
        }
        throw new Error('insert error')
    } catch (e) {
        throw new Error(e)
    }
}

const getDishById = async ({ id }) => {
    if (db === null) throw new Error('no db connection')
    try {
        const dishesCollection = db.collection(DISH_COLLECTION)
        const dish = await dishesCollection.findOne(
            {
                _id: new ObjectId(id),
            },
        )
        return _idToId(dish)
    } catch (e) {
        throw new Error(e)
    }
}

const getDishByCategory = async ({ cat, id }) => {
    if (db === null) throw new Error('no db connection')
    try {
        const dishesCollection = db.collection(DISH_COLLECTION)
        const dish = await dishesCollection.find(
            {
                _id:
                {
                    $ne: new ObjectId(id),
                },
                category: cat,
            },
        ).toArray()
        return _idToIdArray(dish)
    } catch (e) {
        throw new Error(e)
    }
}

module.exports = {
    getDish,
    getTabs,
    getDishById,
    getDishByCategory,
    getUsers,
    addUser,
    getUserByEmail,
    updateTab,
}
