import { Request, Response } from "express";
import { getIO } from "../libs/socket";

import CheckSettingsHelper from "../helpers/CheckSettings";
import AppError from "../errors/AppError";

import CreateUserService from "../services/UserServices/CreateUserService";
import ListUsersService from "../services/UserServices/ListUsersService";
import UpdateUserService from "../services/UserServices/UpdateUserService";
import ShowUserService from "../services/UserServices/ShowUserService";
import DeleteUserService from "../services/UserServices/DeleteUserService";

import ListUser from "../services/UserServices/ListUserParamiterService";
import User from "../models/User";
import { del, get, set } from "../helpers/RedisClient";

import {
  startWhoIsOnlineMonitor,
  stopWhoIsOnlineMonitor
} from "../helpers/WhoIsOnlineMonitor";
import UserOnlineTIme from "../models/UserOnlineTime";

import { format, subMonths } from "date-fns";
import { ptBR } from "date-fns/locale";
import CountTicketsByUserQueue from "../services/UserServices/CountTicketsByUserQueue";
import { splitDateTime } from "../helpers/SplitDateTime";
import ListUserByWhatsappQueuesService from "../services/UserServices/ListUserByWhatsappQueuesService";
import { json } from "sequelize";
import { getSettingValue } from "../helpers/WhaticketSettings";
import { setBotInfo } from "../helpers/SetBotInfo";

type IndexQuery = {
  searchParam: string;
  pageNumber: string;
  profile?: string;
  userId: string;
};

export const index = async (req: Request, res: Response): Promise<Response> => {
  const { searchParam, pageNumber, profile } = req.query as IndexQuery;

  const { users, count, hasMore } = await ListUsersService({
    searchParam,
    pageNumber,
    profile
  });

  if (req.user.profile !== "master") {
    let auxUsers: Array<object> = [];

    // for (var user of users) {
    //   if (user.profile !== 'master') {
    //     auxUsers.push(user)
    //   }
    // }

    for (var user of users) {
      if (user.profile !== "master") {
        if (req.user.profile == "supervisor" && user.profile == "admin")
          continue;

        auxUsers.push(user);
      }
    }

    return res.json({ users: auxUsers, count, hasMore });
  }

  return res.json({ users, count, hasMore });

  //   const { users, count, hasMore } = await ListUsersService({
  //     searchParam,
  //     pageNumber
  //   });

  //   if(req.user.profile!=='master'){

  //     let auxUsers: Array<object>  = [];

  //     for (var user of users) {
  //       if(user.profile!=='master'){
  //         auxUsers.push(user)
  //       }
  //     }

  //     return res.json({ users: auxUsers, count, hasMore });
  //  }

  //   return res.json({ users, count, hasMore });
};

// export const usersByWhatsappQueue = async (req: Request, res: Response): Promise<Response> => {
//   const { profile } = req.query as IndexQuery;

//   const users = await ListUser({
//     profile
//   });

//   return res.json({ users });
// };

export const all = async (req: Request, res: Response): Promise<Response> => {
  let { userId, profile, transferToOtherQueues }: any = req.query as IndexQuery;

  console.log(
    "userId: ",
    userId,
    " | profile: ",
    profile,
    ' | getSettingValue("queueTransferByWhatsappScope")?.value: ',
    getSettingValue("queueTransferByWhatsappScope")?.value
  );

  if (getSettingValue("queueTransferByWhatsappScope")?.value == "enabled" && !transferToOtherQueues) {
    if (!userId) return res.json({ users: [], queues: [] });

    const obj = await ListUserByWhatsappQueuesService(
      userId,
      '"admin", "user", "supervisor"'
    );

    const usersByWhatsqueue = obj.users;
    const queues = obj.queues;

    let userIds = usersByWhatsqueue.map((w: any) => w.userId);

    const users = await ListUser({
      userIds
    });

    return res.json({ users, queues });
  } else {
    const users = await ListUser({
      profile
    });
    return res.json({ users });
  }
};

export const store = async (req: Request, res: Response): Promise<Response> => {
  const {
    email,
    password,
    name,
    profile, 
    positionId,
    queueIds,
    transferToOtherQueues
  } = req.body;

  console.log("===========> req.url: ", req.url);

  if (
    req.url === "/user" &&
    getSettingValue("userCreation")?.value == "disabled" &&
    req.user.profile == "admin"
  ) {
    throw new AppError("ERR_NO_PERMISSION", 403);
  } else if (
    req.url === "/signup" &&
    getSettingValue("userCreation")?.value == "disabled"
  ) {
    throw new AppError("ERR_USER_CREATION_DISABLED", 403);
  } else if (req.user.profile !== "master") {
    throw new AppError("ERR_NO_PERMISSION", 403);
  }

  const user = await CreateUserService({
    email,
    password,
    name, 
    positionId,
    profile,
    queueIds,
    transferToOtherQueues
  });

  if (user) {
    const { id, name } = user;
    await set(`user:${id}`, { id, name });
  }

  const io = getIO();
  io.emit("user", {
    action: "create",
    user
  });

  // await stopWhoIsOnlineMonitor()
  await startWhoIsOnlineMonitor();

  return res.status(200).json(user);
};

export const show = async (req: Request, res: Response): Promise<Response> => {
  const { userId } = req.params;

  const user = await ShowUserService(userId);

  return res.status(200).json(user);
};

export const logoutUser = async (
  req: Request,
  res: Response
): Promise<Response> => {
  const { userId } = req.params;

  await stopWhoIsOnlineMonitor();

  let onlineTime = {
    userId: userId,
    status: "logout..."
  };

  const io = getIO();
  io.emit("onlineStatus", {
    action: "logout",
    userOnlineTime: onlineTime
  });

  await startWhoIsOnlineMonitor();
  //

  return res.status(200).json({});
};

export const update = async (
  req: Request,
  res: Response
): Promise<Response> => {
  if (
    req.user.profile !== "admin" &&
    req.user.profile !== "master" &&
    req.user.profile !== "supervisor"
  ) {
    throw new AppError("ERR_NO_PERMISSION", 403);
  }

  const { userId } = req.params;
  const userData = req.body;

  const dateToday = splitDateTime(
    new Date(format(new Date(), "yyyy-MM-dd HH:mm:ss", { locale: ptBR }))
  );

  const currentDate = new Date();
  const tenMonthsAgo = subMonths(currentDate, 10);
  const formattedDate = format(tenMonthsAgo, "yyyy-MM-dd");
  console.log("dateToday.fullDate: ", dateToday.fullDate);
  console.log("formattedDate 10 months ago: ", formattedDate);

  const openByUserOnQueue: any[] = await CountTicketsByUserQueue({
    startDate: formattedDate,
    endDate: dateToday.fullDate,
    status: "open",
    clientChatStart: true,
    userId: userId
  });

  // console.log('------> openByUserOnQueue: ', openByUserOnQueue)
  // console.log()
  // console.log('------> 1 userData.queueIds: ', userData.queueIds)

  let userQueuesAttendance = [];

  if ((openByUserOnQueue && openByUserOnQueue.length) > 0) {
    userQueuesAttendance = openByUserOnQueue.filter(
      (e: any) => !userData.queueIds.includes(e.queueId)
    );

    if (userQueuesAttendance && userQueuesAttendance.length > 0) {
      const queueInAttendance = userQueuesAttendance.map(e => e.queueId);

      const mergedSet = new Set([...userData.queueIds, ...queueInAttendance]);

      // Convert the Set back to an array
      userData.queueIds = Array.from(mergedSet);

      // console.log('------> 2 userData.queueIds: ', userData.queueIds)
    }
  }

  let user: any = await UpdateUserService({ userData, userId });

  await setBotInfo(user);

  if (user) {
    const { id, name } = user;
    await set(`user:${id}`, { id, name });
  }

  const io = getIO();
  io.emit("user", {
    action: "update",
    user
  });

  user.userQueuesAttendance = userQueuesAttendance;

  return res.status(200).json(user);
};

export const remove = async (
  req: Request,
  res: Response
): Promise<Response> => {
  const { userId } = req.params;

  if (req.user.profile !== "master") {
    throw new AppError("ERR_NO_PERMISSION", 403);
  }

  await DeleteUserService(userId);

  del(`user:${userId}`);

  const io = getIO();
  io.emit("user", {
    action: "delete",
    userId
  });

  //test del
  await stopWhoIsOnlineMonitor();

  io.emit("onlineStatus", {
    action: "delete",
    userOnlineTime: userId
  });

  await startWhoIsOnlineMonitor();
  //

  return res.status(200).json({ message: "User deleted" });
};
