import { Sequelize, WhereOptions, FindOptions, literal, fn, col, Transaction, Op } from "sequelize";
import Models, { sequelize } from "../models";
import { LocalizedContent } from "../../utils/contentGenerator";
import { AppError } from "../../utils/errors";
import _ from 'lodash';

export class ServerDao {
    private accountId: number | null;
    private userId: number | null;
    private language: string;
    private scope: string[] | null;
    private config: userConfig | null;
    constructor(
        private options: {
            language: string;
            scope: string[] | null;
            accountId: number | null;
            userId: number | null;
            config: userConfig | null;
        } = {
                language: process.env.DEFAULT_LANGUAGE_CODE!,
                scope: null,
                config: null,
                userId: null,
                accountId: null,
            }
    ) {
        this.language = options.language;
        this.scope = options.scope ?? [];
        this.config = options.config ?? null;
        this.userId = options.userId ?? null
        this.accountId = options.accountId ?? null
    }

    joinRoom = async (payload: JoinRoomRequest) => {
        const transaction = await sequelize.transaction();
        try {
            const existed = await Models.LiveStreamUser.findOne({
                where: { liveStreamId: payload.liveStreamId, userId: payload.userId, status: payload.status },
                transaction: transaction
            });
            if (!existed) {
                await Models.UserProfile.increment('sessionCount', { by: 1, where: { userId: payload.userId }, transaction: transaction });
                await Models.LiveStreamUser.upsert(
                    { liveStreamId: payload.liveStreamId, userId: payload.userId, status: payload.status },
                    { transaction: transaction }
                );
            }
            await transaction.commit();
            return;
        } catch (err) {
            await transaction.rollback();
            throw new AppError(500, 'SOMETHING_WENT_WRONG_WITH_DAO', err);
        }
    }

    disconnectUser = async (payload: DisconnectRequest) => {
        const transaction = await sequelize.transaction();
        try {
            let anyActiveSession = await Models.Socket.findOne({ where: { userId: payload.userId }, order: [['status', 'desc']], transaction: transaction });
            let returnStatus = 0;
            if (!anyActiveSession) {
                await Models.User.update({ onlineStatus: 0 }, { where: { id: payload.userId }, transaction: transaction });
                let accountSocket = "account_" + payload.accountId;
            } else {
                await Models.User.update({ onlineStatus: anyActiveSession.status == 1 ? 1 : 2 }, { where: { id: payload.userId }, transaction: transaction });
                let accountSocket = "account_" + (payload.accountId ? payload.accountId : "all");
                returnStatus = anyActiveSession == 1 ? 1 : 2;
            }
            await transaction.commit();
            return returnStatus;
        } catch (err) {
            await transaction.rollback();
            throw new AppError(500, 'SOMETHING_WENT_WRONG_WITH_DAO', err);
        }
    }

    userActive = async (payload: UserActiveRequest) => {
        const transaction = await sequelize.transaction();
        try {
            let connectedSession = await Models.Socket.findOne({ where: { socketId: payload.socketId }, transaction: transaction });
            if (connectedSession && payload.userId) {
                await Models.User.update({ onlineStatus: 1 }, { where: { id: payload.userId }, transaction: transaction });
                await connectedSession.update({ status: 1 }, { transaction: transaction })
            }
            await transaction.commit();
            return {};
        } catch (err) {
            await transaction.rollback();
            throw new AppError(500, 'SOMETHING_WENT_WRONG_WITH_DAO', err);
        }
    }

    userAway = async (payload: UserAwayRequest) => {
        const transaction = await sequelize.transaction();
        try {
            let connectedSession = await Models.Socket.findOne({ where: { socketId: payload.socketId }, transaction: transaction });
            if (connectedSession && payload.userId) {
                await connectedSession.update({ status: 0 }, { transaction: transaction });
                let anyOtherActive = await Models.Socket.findOne({ where: { userId: payload.userId, status: 1 }, transaction: transaction });
                if (!anyOtherActive) {
                    await Models.User.update({ onlineStatus: 2 }, { where: { id: payload.userId }, transaction: transaction });
                }
            }
            await transaction.commit();
            return {}
        } catch (err) {
            await transaction.rollback();
            throw new AppError(500, 'SOMETHING_WENT_WRONG_WITH_DAO', err);
        }
    }
}