package com.caliverse.admin.domain.service;

import com.caliverse.admin.domain.dao.admin.EventMapper;
import com.caliverse.admin.domain.datacomponent.MetaDataHandler;
import com.caliverse.admin.domain.entity.*;
import com.caliverse.admin.domain.request.EventRequest;
import com.caliverse.admin.domain.response.EventResponse;
import com.caliverse.admin.dynamodb.service.DynamodbService;
import com.caliverse.admin.global.common.code.CommonCode;
import com.caliverse.admin.global.common.code.ErrorCode;
import com.caliverse.admin.global.common.code.SuccessCode;
import com.caliverse.admin.global.common.constants.MysqlConstants;
import com.caliverse.admin.global.common.utils.CommonUtils;
import com.caliverse.admin.history.service.MysqlHistoryLogService;
import com.fasterxml.jackson.databind.node.ArrayNode;
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.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
@Slf4j
@RequiredArgsConstructor
public class EventService {
    private final DynamoDBService dynamoDBService;
    private final DynamodbService dynamodbService;

    private final EventMapper eventMapper;
    private final MetaDataHandler metaDataHandler;
    private final HistoryService historyService;
    private final MysqlHistoryLogService mysqlHistoryLogService;

    public EventResponse getList(Map requestParam){
        //페이징 처리
        requestParam = CommonUtils.pageSetting(requestParam);

        List<Event> list = eventMapper.getEventList(requestParam);

        int allCnt = eventMapper.getAllCnt(requestParam);

        return EventResponse.builder()
                .status(CommonCode.SUCCESS.getHttpStatus())
                .result(CommonCode.SUCCESS.getResult())
                .resultData(EventResponse.ResultData.builder()
                        .eventList(list)
                        .total(eventMapper.getTotal())
                        .totalAll(allCnt)
                        .pageNo(requestParam.get("page_no")!=null?
                                Integer.valueOf(requestParam.get("page_no").toString()):1)
                        .build()
                )
                .build();
    }

    public EventResponse getDetail(Long id){
        Event event = eventMapper.getEventDetail(id);

        event.setMailList(eventMapper.getMessage(id));
        List<Item> itemList = eventMapper.getItem(id);
        for(Item item : itemList){
            String itemName = metaDataHandler.getMetaItemNameData(Integer.parseInt(item.getItem()));
            item.setItemName(metaDataHandler.getTextStringData(itemName));
        }
        event.setItemList(itemList);

        log.info("getDetail call User Email: {}, event_id: {}", CommonUtils.getAdmin().getEmail(), id);

        return EventResponse.builder()
                .status(CommonCode.SUCCESS.getHttpStatus())
                .result(CommonCode.SUCCESS.getResult())
                .resultData(EventResponse.ResultData.builder()
                        .event(event)
                        .build())
                .build();
    }

    @Transactional(transactionManager = "transactionManager")
    public EventResponse postEvent(EventRequest eventRequest){
        eventRequest.setCreateBy(CommonUtils.getAdmin().getId());

        int result = eventMapper.postEvent(eventRequest);
        log.info("postEvent AdminToolDB Event Save: {}", eventRequest);

        long event_id = eventRequest.getId();

        HashMap<String,String> map = new HashMap<>();
        map.put("mailId",String.valueOf(event_id));

        //아이템 저장
        if(eventRequest.getItemList()!= null && !eventRequest.getItemList().isEmpty()){
            eventRequest.getItemList().forEach(
                    item -> {
                        map.put("goodsId",item.getItem());
                        map.put("itemCnt",String.valueOf(item.getItemCnt()));
                        eventMapper.insertItem(map);
                    }
            );
        }
        log.info("postEvent AdminToolDB Item Save Complete");

        //메시지 저장
        if(eventRequest.getMailList()!= null && !eventRequest.getMailList().isEmpty()){
            eventRequest.getMailList().forEach(
                    item -> {
                        map.put("title",item.getTitle());
                        map.put("content",item.getContent());
                        map.put("language",item.getLanguage());
                        eventMapper.insertMessage(map);
                    }
            );
        }
        log.info("postEvent AdminToolDB Message Save Complete");

        Event event = eventMapper.getEventDetail(event_id);

        mysqlHistoryLogService.insertHistoryLog(
                HISTORYTYPE.EVENT_ADD,
                MysqlConstants.TABLE_NAME_EVENT,
                HISTORYTYPE.EVENT_ADD.name(),
                event,
                CommonUtils.getAdmin().getEmail(),
                CommonUtils.getClientIp()
        );


        //로그 기록
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("type",eventRequest.getEventType());
        jsonObject.put("start_dt",eventRequest.getStartDt());
        jsonObject.put("end_dt",eventRequest.getEndDt());
        jsonObject.put("mail_list",map);
        historyService.setLog(HISTORYTYPE.EVENT_ADD, jsonObject);

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

    @Transactional(transactionManager = "transactionManager")
    public EventResponse updateEvent(Long id, EventRequest eventRequest) {
        eventRequest.setId(id);
        eventRequest.setUpdateBy(CommonUtils.getAdmin().getId());
        eventRequest.setUpdateDt(LocalDateTime.now());

        Long event_id = eventRequest.getId();
        Event before_info = eventMapper.getEventDetail(event_id);
        before_info.setMailList(eventMapper.getMessage(event_id));
        before_info.setItemList(eventMapper.getItem(event_id));

        int result = eventMapper.updateEvent(eventRequest);
        log.info("updateEvent AdminToolDB Event Update Complete: {}", eventRequest);

        Map<String, String> map = new HashMap<>();
        map.put("mailId", String.valueOf(event_id));

        // item 테이블 데이터 삭제 처리 by event_id
        eventMapper.deleteItem(map);

        // 아이템 업데이트
        if (eventRequest.getItemList() != null && !eventRequest.getItemList().isEmpty()) {
            eventRequest.getItemList().forEach(item -> {
                map.put("goodsId", item.getItem());
                map.put("itemCnt", String.valueOf(item.getItemCnt()));

                eventMapper.insertItem(map);
            });
        }
        log.info("updateEvent AdminToolDB Item Update Complete");

        // message 테이블 데이터 삭제 처리 by mail_id
        eventMapper.deleteMessage(map);

        // 메시지 업데이트
        if (eventRequest.getMailList() != null && !eventRequest.getMailList().isEmpty()) {
            eventRequest.getMailList().forEach(item -> {
                map.put("title", item.getTitle());
                map.put("content", item.getContent());
                map.put("language", item.getLanguage());

                eventMapper.insertMessage(map);
            });
        }
        log.info("updateEvent AdminToolDB Message Update Complete");

        Event after_event = eventMapper.getEventDetail(event_id);
        after_event.setMailList(eventMapper.getMessage(event_id));
        after_event.setItemList(eventMapper.getItem(event_id));

        mysqlHistoryLogService.updateHistoryLog(
                HISTORYTYPE.EVENT_UPDATE,
                MysqlConstants.TABLE_NAME_EVENT,
                HISTORYTYPE.EVENT_UPDATE.name(),
                before_info,
                after_event,
                CommonUtils.getAdmin().getEmail(),
                CommonUtils.getClientIp()
        );

        JSONObject jsonObject = new JSONObject();
//        if(result == 1){
//            ObjectMapper objectMapper = new ObjectMapper();
//            ArrayNode mailTitleArray = objectMapper.createArrayNode();
//            ArrayNode mailTextArray = objectMapper.createArrayNode();
//            ArrayNode mailItemArray = objectMapper.createArrayNode();
//            for(Item item : eventRequest.getItemList()){
//                MailItem mailItem = MailItem.newBuilder().setItemId(CommonUtils.stringToInt(item.getItem())).setCount(item.getItemCnt()).build();
//                mailItemArray.add(JsonUtils.createMAilItem(mailItem));
//            }
//            for(Message msg: eventRequest.getMailList()){
//                String langText = msg.getLanguage();
//                int lang;
//
//                if(langText.equals(LANGUAGETYPE.EN.toString())){
//                    lang = LanguageType.LanguageType_en.getNumber();
//                }else if(langText.equals(LANGUAGETYPE.JA.toString())){
//                    lang = LanguageType.LanguageType_ja.getNumber();
//                }else{
//                    lang = LanguageType.LanguageType_ko.getNumber();
//                }
//                SystemMessage titleMessage = SystemMessage.builder().LanguageType(lang).Text(msg.getTitle()).build();
//                SystemMessage textMessage = SystemMessage.builder().LanguageType(lang).Text(msg.getContent()).build();
//
//                mailTitleArray.add(JsonUtils.createSystemMessage(titleMessage));
//                mailTextArray.add(JsonUtils.createSystemMessage(textMessage));
//            }
//
//            String dynamoResult = dynamoDBService.updateSystemMail(
//                    event_id.toString(),
//                    mailTitleArray,
//                    mailTextArray,
//                    eventRequest.getStartDt(),
//                    eventRequest.getEndDt(),
//                    mailItemArray);
//            jsonObject.put("dynamoDB_update",dynamoResult);
//            log.info("updateEvent DynamoDB Update Complete: {}", dynamoResult);
//        }

        //로그 기록
        jsonObject.put("before_event",before_info.toString());
        jsonObject.put("type",eventRequest.getEventType());
        jsonObject.put("start_dt",eventRequest.getStartDt());
        jsonObject.put("end_dt",eventRequest.getEndDt());
        historyService.setLog(HISTORYTYPE.EVENT_UPDATE, jsonObject);

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

    @Transactional(transactionManager = "transactionManager")
    public EventResponse deleteEvent(EventRequest eventRequest){
        Map<String,Object> map = new HashMap<>();

        eventRequest.getList().forEach(
                item->{
                    Long event_id = item.getId();
                    Event event = eventMapper.getEventDetail(event_id);
                    event.setMailList(eventMapper.getMessage(event_id));
                    event.setItemList(eventMapper.getItem(event_id));

                    map.put("mailId",event_id);
                    map.put("desc", item.getDeleteDesc());
                    int result = eventMapper.deleteEvent(map);
                    log.info("updateEvent AdminTool Delete Complete: {}", eventRequest);

                    mysqlHistoryLogService.deleteHistoryLog(
                            HISTORYTYPE.EVENT_DELETE,
                            MysqlConstants.TABLE_NAME_EVENT,
                            HISTORYTYPE.EVENT_DELETE.name(),
                            event,
                            CommonUtils.getAdmin().getEmail(),
                            CommonUtils.getClientIp()
                    );

                    JSONObject jsonObject = new JSONObject();
//                    if(result == 1){
//                        String dynamoResult = dynamoDBService.deleteSystemMail(item.getId().toString());
//                        jsonObject.put("dynamoDB_data",dynamoResult);
//                        log.info("updateEvent dynamoDB Delete Complete: {}", dynamoResult);
//                    }

                    //로그 기록
                    List<Message> message = eventMapper.getMessage(item.getId());
                    if(!message.isEmpty()){
                        jsonObject.put("message",message.get(0).getTitle());
                    }
                    historyService.setLog(HISTORYTYPE.EVENT_DELETE, jsonObject);
                }
        );

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

    public List<Event> getScheduleMailList(){
        return eventMapper.getScheduleEventList();
    }
    public List<Message> getMessageList(Long id){
        return eventMapper.getMessage(id);
    }

    public List<Item> getItemList(Long id){
        return eventMapper.getItem(id);
    }

    @Transactional(transactionManager = "transactionManager")
    public void updateEventStatus(Long id, Event.EVENTSTATUS status){
        Map<String,Object> map = new HashMap<>();
        map.put("id", id);
        map.put("status", status.toString());
        eventMapper.updateStatusEvent(map);
        log.info("updateEventStatus event status changed: {}", status);
    }

    //메타 아이템
    public EventResponse getMetaItem(String metaId){
        long id = Long.parseLong(metaId);
        String item = metaDataHandler.getMetaItemNameData((int) id);
        boolean isItem = (item != null && !item.isEmpty());
        if(isItem) {
            Item item_info = new Item();
            item_info.setItem(metaId);
            item_info.setItemName(metaDataHandler.getTextStringData(item));
            return EventResponse.builder()
                    .status(CommonCode.SUCCESS.getHttpStatus())
                    .result(CommonCode.SUCCESS.getResult())
                    .resultData(EventResponse.ResultData.builder()
                            .message(SuccessCode.ITEM_EXIST.getMessage())
                            .itemInfo(item_info)
                            .build())
                    .build();
        }else
            return EventResponse.builder()
                    .status(CommonCode.ERROR.getHttpStatus())
                    .result(CommonCode.ERROR.getResult())
                    .resultData(EventResponse.ResultData.builder()
                            .message(ErrorCode.NOT_ITEM.getMessage())
                            .build())
                    .build();
    }

    public void insertSystemMail(Event event, ArrayNode mailTitleArray, ArrayNode mailTextArray, ArrayNode mailSenderArray, ArrayNode mailItemArray){
        String dynamoResult = dynamoDBService.insertSystemMail(
                event.getId().intValue(),
                mailTitleArray,
                mailTextArray,
                mailSenderArray,
                event.getStartDt(),
                event.getEndDt(),
                mailItemArray
        );

        eventMapper.updateAddFlag(event.getId());

        historyService.setScheduleLog(HISTORYTYPE.EVENT_ADD, dynamoResult);
        log.info("insertSystemMail Save Complete: {}", dynamoResult);
    }

    @Transactional(transactionManager = "transactionManager")
    public void insertSystemMail(Event event){
        try {
            long event_id = event.getId();
            event.setMailList(eventMapper.getMessage(event_id));
            event.setItemList(eventMapper.getItem(event_id));

            dynamodbService.insertSystemMail(event);

            eventMapper.updateAddFlag(event_id);
            updateEventStatus(event_id, Event.EVENTSTATUS.RUNNING);

            log.info("insertSystemMail Save Complete: {}", event.getId());
        }catch (Exception e){
            log.error("insertSystemMail Exception: {}", e.getMessage());
            updateEventStatus(event.getId(), Event.EVENTSTATUS.FAIL);
        }
    }
}
