import AppError from "../../errors/AppError";
import UserOnlineTime from "../../models/UserOnlineTime";
import { splitDateTime } from "../../helpers/SplitDateTime";
import { Op, Sequelize } from "sequelize";
import { addHours, addMinutes, addSeconds, intervalToDuration, add } from "date-fns";
import format from 'date-fns/format';
import ptBR from 'date-fns/locale/pt-BR';
import { stat } from "fs";
import { getIO } from "../../libs/socket";

import User from '../../models/User'

interface Request {
    userId: string | number,
    status: string,
}

const formatDateTimeString = (date: Date) => {

    let newDate = new Date()
    newDate.setUTCHours(date.getHours())
    newDate.setUTCMinutes(date.getMinutes())
    newDate.setUTCSeconds(date.getSeconds())

    const newD = new Date(newDate);
    const newDateString = newD.toJSON().slice(0, 19).replace('T', ' ');

    return newDateString
}


const CreateOrUpdateUserOnlineTime = async ({
    userId,
    status,
}: Request): Promise<UserOnlineTime> => {

    try {

        const io = getIO();
        let userOnlineTime: any = null;

        const user = await User.findOne({ where: { id: userId } });

        if (!user) {

            return userOnlineTime
        }


        let dateTime = splitDateTime(new Date(format(new Date(), 'yyyy-MM-dd HH:mm:ss', { locale: ptBR })))

        userOnlineTime = await UserOnlineTime.findOne({
            where: {
                [Op.and]: [
                    {
                        userId: userId
                    },
                    {
                        "$createdAt$": Sequelize.where(Sequelize.fn("date", Sequelize.col("createdAt")), `${dateTime.fullDate}`)
                    },
                ]
            }
        });

        if (userOnlineTime) {
            try {

                let oldStatus = userOnlineTime.status




                if (oldStatus == 'online' && status === 'offline') {
                    //updatedAt
                    let newtTime = intervalToDuration({ start: userOnlineTime.updatedAt, end: new Date() })




                    let onlineTime = new Date()

                    onlineTime.setUTCHours(userOnlineTime.onlineTime.getHours())
                    onlineTime.setUTCMinutes(userOnlineTime.onlineTime.getMinutes())
                    onlineTime.setUTCSeconds(userOnlineTime.onlineTime.getSeconds())



                    if (newtTime.hours && +newtTime.hours > 0) {
                        onlineTime = addHours(onlineTime, newtTime.hours)
                    }
                    if (newtTime.minutes && +newtTime.minutes > 0) {
                        onlineTime = addMinutes(onlineTime, newtTime.minutes)
                    }
                    if (newtTime.seconds && +newtTime.seconds > 0) {
                        onlineTime = addSeconds(onlineTime, newtTime.seconds)
                    }



                    const isoDate = new Date(onlineTime);
                    const mySQLDateString = isoDate.toJSON().slice(0, 19).replace('T', ' ');


                    await userOnlineTime.update({ status, onlineTime: mySQLDateString })

                    //test del  

                    const updatedAtString = formatDateTimeString(userOnlineTime.updatedAt)
                    const createdAtString = formatDateTimeString(userOnlineTime.createdAt)



                    // 


                    io.emit("onlineStatus", {
                        action: "update",
                        userOnlineTime: {
                            userId: userOnlineTime.userId,
                            status: userOnlineTime.status,
                            onlineTime: mySQLDateString,
                            createdAt: createdAtString,
                            updatedAt: updatedAtString
                        }
                    });

                }
                else if (oldStatus == 'offline' && status === 'online') {
                    await userOnlineTime.update({ status })

                    io.emit("onlineStatus", {
                        action: "update",
                        userOnlineTime: {
                            userId: userOnlineTime.userId,
                            status: userOnlineTime.status,
                            createdAt: formatDateTimeString(userOnlineTime.createdAt),
                            updatedAt: formatDateTimeString(userOnlineTime.updatedAt)
                        }
                    });
                }
                else {
                    console.log('NOT UPDATED THE USER: ', userOnlineTime.userId)
                }

            } catch (err) {

                throw new AppError("ERR_NO_USER_ONLINE_FOUND", 404);

            }
        }

        if (!userOnlineTime) {

            userOnlineTime = await UserOnlineTime.create(
                {
                    userId,
                    status,
                    onlineTime: `${dateTime.fullDate} 00:00:00`
                })

            io.emit("onlineStatus", {
                action: "update",
                userOnlineTime: {
                    userId: userOnlineTime.userId,
                    status: userOnlineTime.status,
                    createdAt: formatDateTimeString(userOnlineTime.createdAt),
                    updatedAt: formatDateTimeString(userOnlineTime.updatedAt)
                }
            });



        }


        return userOnlineTime

    } catch (error: any) {
        console.error('===> Error on CreateOrUpdateUserOnlineTime.ts file: \n', error)
        throw new AppError(error.message);
    }

}



export default CreateOrUpdateUserOnlineTime