import { Op, fn, where, col, Filterable, Includeable } from "sequelize";
import { startOfDay, endOfDay, parseISO, format } from "date-fns";
import ptBR from "date-fns/locale/pt-BR";

import Ticket from "../../models/Ticket";
import Contact from "../../models/Contact";
import Message from "../../models/Message";
import Queue from "../../models/Queue";
import ShowUserService from "../UserServices/ShowUserService";

const unflatten = require("flat").unflatten;

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

import { getWbot } from "../../libs/wbot";
import User from "../../models/User";
import { get } from "../../helpers/RedisClient";
import monthsAgo from "../../helpers/MonthsAgo";

interface Request {
  searchParam?: string;
  pageNumber?: string;
  status?: string;
  date?: string;
  showAll?: string;
  userId: string;
  withUnreadMessages?: string;
  queueIds: number[];
  unlimited?: string;
  searchParamContent?: string;
}

interface Response {
  tickets: Ticket[];
  count: number;
  hasMore: boolean;
  remoteTicketsControll?: object[];
}

const ListTicketsService = async ({
  searchParam = "",
  pageNumber = "1",
  queueIds,
  status,
  date,
  showAll,
  userId,
  withUnreadMessages,
  unlimited = "false",
  searchParamContent = ""
}: Request): Promise<Response> => {
  console.log(
    "----------> searchParamContent: ",
    searchParamContent,
    " | searchParam: ",
    searchParam
  );

  let whereCondition: Filterable["where"] = {
    [Op.or]: [{ userId }, { status: "pending" }],
    queueId: { [Op.or]: [queueIds, null] }
  };

  console.log("PAGE NUMBER TICKET: ", pageNumber);

  if (pageNumber.trim().length == 0) {
    pageNumber = "1";
  }

  // if (searchParam && searchParam.trim().length > 0 && process.env.CACHE) {
  //   try {
  //     const offset = 40 * (+pageNumber - 1);

  //     searchParam = searchParam.replace(/\s+/g, " ").trim().toLowerCase();

  //     console.log("QUERY TICKET SEARCH PARAM FROM CACHE: ", searchParam);

  //     let tickets: any = await searchTicketCache(searchParam, offset, 40);

  //     if (tickets) {
  //       console.log(
  //         "QUERY TICKET SEARCH PARAM FROM CACHE LENGTH...: ",
  //         tickets.length
  //       );

  //       tickets.map((t: any) => {
  //         t["contact.number"] = t["contact_number"];
  //         delete t["contact_number"];

  //         return { ...["contact_number"] };
  //       });

  //       tickets = tickets.map((e: any) => unflatten(e));

  //       return {
  //         tickets,
  //         count: tickets.length,
  //         hasMore: tickets.length > 0 ? true : false
  //       };
  //     }
  //   } catch (error) {
  //     console.log(
  //       "There was an error on search ListTicketservice.ts search cache: ",
  //       error
  //     );
  //   }

  //   console.log("QUERY TICKETS FROM DATABASE...");
  // }

  let includeCondition: Includeable[];

  includeCondition = [
    {
      model: Contact,
      as: "contact",
      attributes: ["id", "name", "number", "profilePicUrl"]
    },
    {
      model: Queue,
      as: "queue",
      attributes: ["id", "name", "color"]
    }
  ];

  if (showAll === "true") {
    whereCondition = { queueId: { [Op.or]: [queueIds, null] } };
  }

  if (status) {
    whereCondition = { ...whereCondition, status };

    if (unlimited === "current" && status !== "pending") {
      whereCondition = {
        ...whereCondition,
        createdAt: {
          [Op.gte]: dateToday.fullDate + " 00:00:00.000000",
          [Op.lte]: dateToday.fullDate + " 23:59:59.999999"
        }
      };
    }
  }

  if (searchParam) {
    const sanitizedSearchParam = searchParam.toLocaleLowerCase().trim();

    includeCondition = [
      ...includeCondition,
      {
        model: Message,
        as: "messages",
        attributes: ["id", "body"],
        where: {
          body: where(
            fn("LOWER", col("body")),
            "LIKE",
            `%${sanitizedSearchParam}%`
          )
        },
        required: false,
        duplicating: false
      }
    ];

    whereCondition = {
      ...whereCondition,
      createdAt: {
        [Op.gte]: monthsAgo(4) + " 00:00:00.000000",
        [Op.lte]: dateToday.fullDate + " 23:59:59.999999"
      }
    };

    whereCondition = {
      ...whereCondition,
      [Op.or]: [
        {
          "$contact.name$": where(
            fn("LOWER", col("contact.name")),
            "LIKE",
            `%${sanitizedSearchParam}%`
          )
        },
        { "$contact.number$": { [Op.like]: `%${sanitizedSearchParam}%` } },
        {
          "$message.body$": where(
            fn("LOWER", col("body")),
            "LIKE",
            `%${sanitizedSearchParam}%`
          )
        }
      ]
    };

    // const sanitizedSearchParamContent = searchParamContent
    //   .toLocaleLowerCase()
    //   .trim();

    // if (searchParamContent.length > 0) {
    //   includeCondition = [
    //     ...includeCondition,
    //     {
    //       model: Message,
    //       as: "messages",
    //       attributes: ["id", "body"],
    //       where: {
    //         body: where(
    //           fn("LOWER", col("body")),
    //           "LIKE",
    //           `%${sanitizedSearchParamContent}%`
    //         )
    //       },
    //       required: false,
    //       duplicating: false
    //     }
    //   ];

    //   whereCondition = {
    //     ...whereCondition,
    //     "$message.body$": where(
    //       fn("LOWER", col("body")),
    //       "LIKE",
    //       `%${sanitizedSearchParamContent}%`
    //     )
    //   };
    // }

    // whereCondition = {
    //   ...whereCondition,
    //   [Op.or]: [
    //     {
    //       "$contact.name$": where(
    //         fn("LOWER", col("contact.name")),
    //         "LIKE",
    //         `%${sanitizedSearchParam}%`
    //       )
    //     },

    //     { "$contact.number$": { [Op.like]: `%${sanitizedSearchParam}%` } }
    //   ]
    // };

    const userProfile: any = await User.findByPk(userId);

    if (
      userProfile.dataValues.profile != "admin" &&
      userProfile.dataValues.profile != "master" &&
      userProfile.dataValues.profile != "supervisor"
    ) {
      whereCondition = { ...whereCondition, userId };
    }
  }

  if (date) {
    whereCondition = {
      createdAt: {
        [Op.between]: [+startOfDay(parseISO(date)), +endOfDay(parseISO(date))]
      },
      queueId: { [Op.or]: [queueIds, null] },
    };
  }

  if (withUnreadMessages === "true") {
    const user = await ShowUserService(userId);
    const userQueueIds = user.queues.map(queue => queue.id);

    whereCondition = {
      [Op.or]: [{ userId }, { status: "pending" }],
      queueId: { [Op.or]: [userQueueIds, null] },
      unreadMessages: { [Op.gt]: 0 }
    };
  }

  let limit;

  if (unlimited === "current") limit = 10000;
  else if (unlimited === "all") limit = 100;
  else limit = 40;

  // const limit = unlimited === "current" || unlimited === "all" ? 1000 : 40;
  const offset = limit * (+pageNumber - 1);

  console.log("kkkkkkkkk limit: ", limit);

  let { count, rows: tickets } = await Ticket.findAndCountAll({
    where: whereCondition,
    include: includeCondition,
    distinct: true,
    limit,
    offset,
    order: [["updatedAt", "DESC"]]
  });

  const hasMore = count > offset + tickets.length;

  const ticketIds = await get({ key: `remote:controll`, parse: true });

  return {
    tickets,
    count,
    hasMore,
    remoteTicketsControll: ticketIds ? ticketIds : []
  };
};

export default ListTicketsService;
