package com.caliverse.admin.domain.service;

import com.caliverse.admin.domain.dao.admin.DataMapper;
import com.caliverse.admin.domain.dao.admin.LandMapper;
import com.caliverse.admin.domain.entity.*;
import com.caliverse.admin.domain.entity.log.LogAction;
import com.caliverse.admin.domain.request.DataRequest;
import com.caliverse.admin.domain.request.LogGenericRequest;
import com.caliverse.admin.domain.response.DataResponse;
import com.caliverse.admin.dynamodb.service.DynamodbDataService;
import com.caliverse.admin.global.common.annotation.BusinessProcess;
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.mongodb.domain.APILogInfo;
import com.caliverse.admin.mongodb.service.DataInitializeHistoryService;
import com.caliverse.admin.mongodb.service.MysqlHistoryLogService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.mongodb.UncategorizedMongoDbException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
@Service
@RequiredArgsConstructor
public class DataService {

    private final DynamodbDataService dynamodbDataService;
    private final LandMapper landMapper;
    private final DataMapper dataMapper;
    private final DataInitializeHistoryService dataInitializeHistoryService;


    public DataResponse initHistoryList(LogGenericRequest logGenericRequest){

        LocalDateTime startDt = logGenericRequest.getStartDt().plusHours(9);
        LocalDateTime endDt = logGenericRequest.getEndDt().plusHours(9).plusDays(1);

        logGenericRequest.setStartDt(startDt);
        logGenericRequest.setEndDt(endDt);

        List<APILogInfo> logList = new ArrayList<>();
        try{
            logList = dataInitializeHistoryService.loadHistoryData(logGenericRequest, APILogInfo.class);
        }catch(UncategorizedMongoDbException e){
            if (e.getMessage().contains("Sort exceeded memory limit")) {
                log.error("MongoDB Query memory limit error: {}", e.getMessage());
                return DataResponse.builder()
                        .status(CommonCode.ERROR.getHttpStatus())
                        .result(ErrorCode.ERROR_LOG_MEMORY_LIMIT.toString())
                        .build();
            } else {
                log.error("MongoDB Query error", e);
                return DataResponse.builder()
                        .status(CommonCode.ERROR.getHttpStatus())
                        .result(ErrorCode.ERROR_MONGODB_QUERY.toString())
                        .build();
            }
        }catch (Exception e){
            log.error("dataInitialize error", e);
        }

        return DataResponse.builder()
                .resultData(DataResponse.ResultData.builder()
                        .dataInitList(logList)
                        .build())
                .status(CommonCode.SUCCESS.getHttpStatus())
                .result(CommonCode.SUCCESS.getResult())
                .build();

    }

    @BusinessProcess(action = LogAction.DATA)
    @Transactional(transactionManager = "transactionManager")
    public DataResponse initData(DataRequest dataRequest){
        EInitDataType dataType = dataRequest.getInitDataType();
        dataRequest.setCreateBy(CommonUtils.getAdmin().getId());
        log.info("initData email: {}, initDataType: {}", CommonUtils.getAdmin().getEmail(), dataType);

        dataMapper.postDataInit(dataRequest);

//        switch(dataType){
//            case LandAuction -> {
//                int result = initLandAuction();
//                if(result == 0){
//                    return DataResponse.builder()
//                            .status(CommonCode.ERROR.getHttpStatus())
//                            .result(ErrorCode.ERROR_DATA_INIT.toString())
//                            .build();
//                }
//            }
//            case LandOwned -> {
//                int result = initLandOwned();
//                if(result == 0){
//                    return DataResponse.builder()
//                            .status(CommonCode.ERROR.getHttpStatus())
//                            .result(ErrorCode.ERROR_DATA_INIT.toString())
//                            .build();
//                }
//            }
//        }
//
//        dynamodbDataService.InitDataLandOwned();

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

    @Transactional(transactionManager = "transactionManager")
    public void initLandAuction(LandAuction landAuction){
        try {
            long auctionId = landAuction.getId();
            int result = landMapper.initLandAuction(auctionId);

            dataInitializeHistoryService.mysqlDataInitHistory(
                    EInitDataType.LandAuction,
                    MysqlConstants.TABLE_NAME_LAND_AUCTION,
                    true,
                    "SUCCESS",
                    landAuction
            );

        }catch(Exception e){
            log.error("InitLandAuction Delete Error: {}", e.getMessage());
            dataInitializeHistoryService.mysqlDataInitHistory(
                    EInitDataType.LandAuction,
                    MysqlConstants.TABLE_NAME_LAND_AUCTION,
                    false,
                    e.getMessage(),
                    landAuction
            );
        }
    }

    public void initLandOwned(LandOwnerChange landOwnerChange){
        try {
            long id = landOwnerChange.getId();
            landMapper.initLandOwnedChanges(id);

            dataInitializeHistoryService.mysqlDataInitHistory(
                    EInitDataType.LandOwned,
                    MysqlConstants.TABLE_NAME_LAND_OWNER_CHANGE,
                    true,
                    "SUCCESS",
                    landOwnerChange
            );
        }catch(Exception e){
            log.error("initLandOwned Delete Error: {}", e.getMessage());
            dataInitializeHistoryService.mysqlDataInitHistory(
                    EInitDataType.LandOwned,
                    MysqlConstants.TABLE_NAME_LAND_OWNER_CHANGE,
                    false,
                    e.getMessage(),
                    landOwnerChange
            );
        }
    }

    public List<DataInit> getScheduleDataInitList(){
        return dataMapper.getDataInit();
    }

    @BusinessProcess(action = LogAction.DATA)
    public void updateStatus(long id, DataInit.DATA_INIT_STATUS status){
        dataMapper.updateStatus(id, status.toString());
    }
}
