package com.caliverse.admin.domain.RabbitMq;

import com.caliverse.admin.domain.RabbitMq.message.LogoutReasonType;
import com.caliverse.admin.domain.RabbitMq.message.MailItem;
import com.caliverse.admin.domain.RabbitMq.message.OperationSystemMessage;
import com.caliverse.admin.domain.RabbitMq.message.ServerMessage;
import com.caliverse.admin.domain.entity.log.LogStatus;
import com.caliverse.admin.global.common.constants.CommonConstants;
import com.caliverse.admin.global.common.utils.CommonUtils;
import com.caliverse.admin.mongodb.service.BusinessLogService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.concurrent.CompletableFuture;

@Slf4j
@Service
public class MessageHandlerService {

    private final RabbitMqService rabbitMqService;
    private final BusinessLogService businessLogService;

    public MessageHandlerService(RabbitMqService rabbitMqService, BusinessLogService businessLogService) {
        this.rabbitMqService = rabbitMqService;
        this.businessLogService = businessLogService;
    }

    private void logMessage(LogStatus logStatus, String message, String queName, String serverName, Object content){
        CompletableFuture<String> logFuture = businessLogService.logMessageQueue(
                logStatus,
                message,
                CommonUtils.getAdmin() == null ? CommonConstants.SYSTEM : CommonUtils.getAdmin().getEmail(),
                CommonUtils.getClientIp() == null ? CommonConstants.SYSTEM : CommonUtils.getClientIp(),
                queName,
                serverName,
                content
        );

        logFuture.whenComplete((result, throwable) -> {
            if (throwable != null) {
                log.warn("MessageQueue Business log failed for info: {}, error: {}", CommonUtils.objectByString(content), throwable.getMessage());
            }
        });
    }

    public void sendUserKickMessage(String userGuid, String serverName, String reason){
        try {
            var user_kick_builder = ServerMessage.MOS2GS_NTF_USER_KICK.newBuilder();
            user_kick_builder.setUserGuid(userGuid);
            user_kick_builder.setKickReasonMsg(String.format("backoffice %s", reason));
            user_kick_builder.setLogoutReasonType(LogoutReasonType.LogoutReasonType_None);

            rabbitMqService.SendMessage(user_kick_builder.build(), serverName);

            log.info("Send User Kick Message to Server: {}, user: {}", serverName, userGuid);

            logMessage(
                    LogStatus.SUCCESS,
                    "",
                    "sendUserKickMessage",
                    serverName,
                    user_kick_builder.build()
            );
        }catch(Exception e){
            log.error(e.getMessage());
            logMessage(
                    LogStatus.FAILURE,
                    String.format("User Kick Fail UserGuid: %s, reason: %s, error: %s", userGuid, reason, e.getMessage()),
                    "sendUserKickMessage",
                    serverName,
                    null
            );
        }
    }

    public void sendNoticeMessage(List<String> serverList, String type, List<OperationSystemMessage> msgList, List<OperationSystemMessage> senderList){
        try {
            var noticeBuilder = ServerMessage.MOS2GS_NTF_NOTICE_CHAT.newBuilder();
            noticeBuilder.addNoticeType(type);

            for (OperationSystemMessage msg : msgList) {
                noticeBuilder.addChatMessage(msg);
            }
            for (OperationSystemMessage sender : senderList) {
                noticeBuilder.addSender(sender);
            }
            for (String server : serverList) {
                rabbitMqService.SendMessage(noticeBuilder.build(), server);
            }

            log.info("Send Notice Message to Server: {}, type: {}", serverList.toString(), type);

            logMessage(
                    LogStatus.SUCCESS,
                    "",
                    "sendNoticeMessage",
                    serverList.toString(),
                    noticeBuilder.build()
            );
        }catch (Exception e){
            log.error(e.getMessage());
            logMessage(
                    LogStatus.FAILURE,
                    String.format("Send Notice Fail Type: %s, senderList: %s, msgList: %s, error: %s", type, senderList.toString(), msgList.toString(), e.getMessage()),
                    "sendNoticeMessage",
                    serverList.toString(),
                    null
            );
        }
    }

    public void sendMailMessage(String serverName, String userGuid, String mailType, List<OperationSystemMessage> titleList, List<OperationSystemMessage> msgList
            , List<MailItem> itemList, List<OperationSystemMessage> senderList){
        try {
            var mail_builder = ServerMessage.MOS2GS_NTF_MAIL_SEND.newBuilder();
            mail_builder.setUserGuid(userGuid);
            mail_builder.setMailType(mailType);

            for (OperationSystemMessage title : titleList) {
                mail_builder.addTitle(title);
            }
            for (OperationSystemMessage msg : msgList) {
                mail_builder.addMsg(msg);
            }
            for (MailItem item : itemList) {
                mail_builder.addItemList(item);
            }
            for (OperationSystemMessage sender : senderList) {
                mail_builder.addSender(sender);
            }
            rabbitMqService.SendMessage(mail_builder.build(), serverName);

            log.info("Send Mail Message to Server: {}, user: {}", serverName, userGuid);

            logMessage(
                    LogStatus.SUCCESS,
                    "",
                    "sendMailMessage",
                    serverName,
                    mail_builder.build()
            );
        }catch (Exception e){
            log.error(e.getMessage());
            logMessage(
                    LogStatus.FAILURE,
                    String.format("Send Mail Fail UserGuid: %s, mailType: %s, senderList: %s, titleList: %s, itemList: %s, error: %s",
                            userGuid, mailType, senderList.toString(), titleList.toString(), itemList.toString(), e.getMessage()),
                    "sendMailMessage",
                    serverName,
                    null
            );
        }
    }

    public void sendBannerMessage(String serverName){
        try {
            var banner_builder = ServerMessage.MOS2GS_NTF_UPDATE_BANNER.newBuilder();

            rabbitMqService.SendMessage(banner_builder.build(), serverName);

            log.info("Send Banner Message to Server: {}", serverName);

            logMessage(
                    LogStatus.SUCCESS,
                    "",
                    "sendBannerMessage",
                    serverName,
                    banner_builder.build()
            );
        }catch(Exception e){
            log.error(e.getMessage());
            logMessage(
                    LogStatus.FAILURE,
                    String.format("Banner Fail error: %s", e.getMessage()),
                    "sendBannerMessage",
                    serverName,
                    null
            );
        }
    }

    public void sendQuestTaskCompleteMessage(String serverName, String accountId, int reqId, String questKey, int taskId){
        try {
            var quest_task_builder = ServerMessage.MOS2GS_NTF_QUEST_TASK_FORCE_COMPLETE.newBuilder();
            quest_task_builder.setAccountId(accountId);
            quest_task_builder.setReqId(reqId);
            quest_task_builder.setQuestKey(questKey);
            quest_task_builder.setTaskId(taskId);

            rabbitMqService.SendMessage(quest_task_builder.build(), serverName);

            log.info("Send Quest Task Complete Message to Server: {}, accountId: {}, questKey: {}, taskId: {}", serverName, accountId, questKey, taskId);

            logMessage(
                    LogStatus.SUCCESS,
                    "",
                    "sendQuestTaskCompleteMessage",
                    serverName,
                    quest_task_builder.build()
            );
        }catch(Exception e){
            log.error(e.getMessage());
            logMessage(
                    LogStatus.FAILURE,
                    String.format("Quest Task Complete Fail accountId: %s, questKey: %s, taskId: %s, error: %s", accountId, questKey, taskId, e.getMessage()),
                    "sendQuestTaskCompleteMessage",
                    serverName,
                    null
            );
        }
    }

    public void sendRankingScheduleMessage(String serverName){
        try {
            var ranking_schedule_builder = ServerMessage.MOS2GS_NTF_UPDATE_RANKING_SCHEDULE.newBuilder();

            rabbitMqService.SendMessage(ranking_schedule_builder.build(), serverName);

            log.info("Send Ranking Schedule Message to Server: {}", serverName);

            logMessage(
                    LogStatus.SUCCESS,
                    "",
                    "sendRankingScheduleMessage",
                    serverName,
                    ranking_schedule_builder.build()
            );
        }catch(Exception e){
            log.error(e.getMessage());
            logMessage(
                    LogStatus.FAILURE,
                    String.format("Ranking Schedule Fail error: %s", e.getMessage()),
                    "sendRankingScheduleMessage",
                    serverName,
                    null
            );
        }
    }
}

