package com.caliverse.admin.domain.service;

import com.caliverse.admin.domain.dao.admin.HistoryMapper;
import com.caliverse.admin.domain.dao.admin.NoticeMapper;
import com.caliverse.admin.domain.entity.HISTORYTYPE;
import com.caliverse.admin.domain.entity.InGame;
import com.caliverse.admin.domain.entity.Message;
import com.caliverse.admin.domain.request.NoticeRequest;
import com.caliverse.admin.domain.response.NoticeResponse;
import com.caliverse.admin.global.common.code.CommonCode;
import com.caliverse.admin.global.common.code.SuccessCode;
import com.caliverse.admin.global.common.utils.CommonUtils;
import com.caliverse.admin.scheduler.ScheduleService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.json.JSONObject;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Slf4j
@Service
@RequiredArgsConstructor
public class NoticeService {

    private final NoticeMapper noticeMapper;
    private final HistoryMapper historyMapper;
    private final ScheduleService scheduleService;
    private final HistoryService historyService;

    public NoticeResponse getNoticeList(){

        List<InGame> noticeList = noticeMapper.getNoticeList();

        return NoticeResponse.builder()
                .resultData(NoticeResponse.ResultData.builder()
                        .list(noticeList).build())
                .status(CommonCode.SUCCESS.getHttpStatus())
                .result(CommonCode.SUCCESS.getResult())
                .build();
    }
    public NoticeResponse getNoticeDetail(Long id){

        NoticeResponse.ResultData resultData = null;
        log.info("getNoticeDetail id::"+id);

        InGame inGame = noticeMapper.getNoticeDetail(id);

        if(inGame != null){
            List<Message> noticeMessage = noticeMapper.getMessage(inGame.getId());

            resultData = NoticeResponse.ResultData.builder()
                    .gameMessages(noticeMessage)
                    .inGame(inGame)
                    .build();
        }else{
            // 조회된 데이터가 없습니다.
            return NoticeResponse.builder()
                    .resultData(NoticeResponse.ResultData.builder().message(SuccessCode.NULL_DATA.getMessage()).build())
                    .status(CommonCode.SUCCESS.getHttpStatus())
                    .result(CommonCode.SUCCESS.getResult())
                    .build();
        }

        return NoticeResponse.builder()
                .resultData(resultData)
                .status(CommonCode.SUCCESS.getHttpStatus())
                .result(CommonCode.SUCCESS.getResult())
                .build();
    }

    //인게임 메시지 등록
    @Transactional(transactionManager = "transactionManager")
    public NoticeResponse postInGameMessage(NoticeRequest noticeRequest){
        // 등록자는 메일로 넣어주자
        noticeRequest.setCreateBy(CommonUtils.getAdmin().getId());
        // notice 테이블 insert
        int i = noticeMapper.postNotice(noticeRequest);
        if(i > 0){
            Map<String,Object> map = new HashMap<>();
            noticeRequest.getGameMessages().stream()
                    .filter(item -> !item.getContent().isEmpty())
                    .map(item -> {
                        map.put("id", noticeRequest.getId());
                        map.put("language", item.getLanguage());
                        map.put("content", item.getContent());
                        //메시지 테이블 insert
                        noticeMapper.insertMessage(map);
                        return item;
            }).collect(Collectors.toList());
        }
        log.info("postInGameMessage notice: {}", noticeRequest);

        //로그 기록
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("message_type",noticeRequest.getMessageType());
        jsonObject.put("repeat_type",noticeRequest.getRepeatType());
        jsonObject.put("repeat_cnt",noticeRequest.getRepeatCnt());
        jsonObject.put("repeat_dt",noticeRequest.getRepeatDt());
        jsonObject.put("send_dt",noticeRequest.getSendDt());
        jsonObject.put("end_dt",noticeRequest.getEndDt());
        jsonObject.put("message",noticeRequest.getGameMessages().toString());
        historyService.setLog(HISTORYTYPE.NOTICE_ADD, jsonObject);

        return NoticeResponse.builder()
                .resultData(NoticeResponse.ResultData.builder().message(SuccessCode.REGISTRATION.getMessage()).build())
                .result(CommonCode.SUCCESS.getResult())
                .status(CommonCode.SUCCESS.getHttpStatus())
                .build();
    }

    @Transactional(transactionManager = "transactionManager")
    public NoticeResponse updateInGameMessage(Long id, NoticeRequest noticeRequest){
        noticeRequest.setId(id);
        noticeRequest.setUpdateBy(CommonUtils.getAdmin().getId());
        int i = noticeMapper.updateNotice(noticeRequest);
        // 스케줄에서 기존 등록 제거
        scheduleService.closeTask(noticeRequest.getId().toString());
        if(i > 0){
            InGame before_notice = noticeMapper.getNoticeDetail(noticeRequest.getId());
            log.info("updateInGameMessage Before notice: {}", before_notice);

            Map<String, Object> map = new HashMap<>();
            //선 삭제 후 insert
            noticeMapper.deleteMessage(noticeRequest.getId());

            for (Message item : noticeRequest.getGameMessages()) {
                String content = item.getContent();

                // content가 null이거나 빈 문자열인 경우 루프 건너뛰기
                if (content == null || content.isEmpty()) {
                    continue;
                }

                map.put("id", noticeRequest.getId());
                map.put("language", item.getLanguage());
                map.put("content", content);
                // 메시지 테이블 insert
                noticeMapper.insertMessage(map);
            }
        }
        log.info("updateInGameMessage After notice: {}", noticeRequest);
        return NoticeResponse.builder()
                .resultData(NoticeResponse.ResultData.builder().message(SuccessCode.UPDATE.getMessage()).build())
                .result(CommonCode.SUCCESS.getResult())
                .status(CommonCode.SUCCESS.getHttpStatus())
                .build();
    }

    @Transactional(transactionManager = "transactionManager")
    public NoticeResponse deleteInGameMessage(NoticeRequest noticeRequest){

        Map<String, Object> map = new HashMap<>();
        noticeRequest.getList().forEach(
                item->{

                    //사용자 로그 기록 (인게임 메시지 삭제)
                    String message = noticeMapper.getMessageById(item.getMessageId());

                    noticeMapper.deleteNotice(item.getMessageId());

                    // 스케줄에서 제거
                    scheduleService.closeTask("notice-" + item.getMessageId());

                    log.info("deleteInGameMessage notice: {}", item);

                    //로그 기록
                    map.put("adminId",  CommonUtils.getAdmin().getId());
                    map.put("name",  CommonUtils.getAdmin().getName());
                    map.put("mail",  CommonUtils.getAdmin().getEmail());
                    map.put("type", HISTORYTYPE.NOTICE_DELETE);
                    JSONObject jsonObject = new JSONObject();
                    jsonObject.put("message",message);
                    map.put("content",jsonObject.toString());
                    historyMapper.saveLog(map);
                }
        );
        log.info("deleteInGameMessage notice: {}", noticeRequest);
        return NoticeResponse.builder()
                .resultData(NoticeResponse.ResultData.builder().message(SuccessCode.DELETE.getMessage()).build())
                .result(CommonCode.SUCCESS.getResult())
                .status(CommonCode.SUCCESS.getHttpStatus())
                .build();
    }

    public List<InGame> getScheduleNoticeList(){
        return noticeMapper.getSchesuleNoticeList();
    }

    public List<Message> getNoticeMessageList(Long id){
        return noticeMapper.getMessage(id);
    }

    public void updateNoticeStatus(Long id, InGame.SENDSTATUS status){
        HashMap map = new HashMap();
        map.put("id", id);
        map.put("status", status.toString());
        noticeMapper.updateStatusNotice(map);
    }

    public void updateNoticeCount(Long id){
        noticeMapper.updateCountNotice(id);
    }

    public void setScheduleLog(HISTORYTYPE type, String message){
        //스케줄 로그 기록
        Map<String, Object> logMap = new HashMap<>();
        logMap.put("adminId",  1);
        logMap.put("name",  "schedule");
        logMap.put("mail",  "schedule");
        logMap.put("type", type);
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("message",message);
        logMap.put("content",jsonObject.toString());
        historyMapper.saveLog(logMap);
    }
}
