package com.caliverse.admin.domain.service;

import com.caliverse.admin.domain.dao.admin.BlackListMapper;
import com.caliverse.admin.domain.entity.BlackList;
import com.caliverse.admin.domain.entity.Excel;
import com.caliverse.admin.domain.entity.HISTORYTYPEDETAIL;
import com.caliverse.admin.domain.entity.log.LogAction;
import com.caliverse.admin.domain.request.BlackListRequest;
import com.caliverse.admin.domain.response.BlackListResponse;
import com.caliverse.admin.dynamodb.service.DynamodbUserService;
import com.caliverse.admin.global.common.annotation.BusinessProcess;
import com.caliverse.admin.global.common.annotation.RequestLog;
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.CommonConstants;
import com.caliverse.admin.global.common.constants.MysqlConstants;
import com.caliverse.admin.global.common.exception.RestApiException;
import com.caliverse.admin.global.common.utils.CommonUtils;
import com.caliverse.admin.global.common.utils.ExcelUtils;
import com.caliverse.admin.mongodb.service.MysqlHistoryLogService;
import lombok.RequiredArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

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

@Service
@RequiredArgsConstructor
public class BlackListService {
    private static final Logger logger = LoggerFactory.getLogger(BlackListService.class);
    private final BlackListMapper blackListMapper;
    private final ExcelUtils excelUtils;
    private final DynamodbUserService dynamodbUserService;
    private final MysqlHistoryLogService mysqlHistoryLogService;
    @Value("${caliverse.file}")
    private String excelPath;
    private final ResourceLoader resourceLoader;

    @RequestLog
    public BlackListResponse getBlackList(Map requestParams){
        //페이징 처리
        requestParams = CommonUtils.pageSetting(requestParams);

        List<BlackList> blackList = blackListMapper.getBlackList(requestParams);

        int allCnt = blackListMapper.getAllCnt(requestParams);

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

    @RequestLog
    public BlackListResponse getBlackListDetail(Long id ){
        BlackList blackList = blackListMapper.getBlackListDetail(id);
        List<BlackList> historyByGuid = blackListMapper.getHistoryByGuid(blackList.getGuid());
        blackList.setBlackListHistory(historyByGuid);
        return BlackListResponse.builder()
                .resultData(BlackListResponse.ResultData.builder()
                        .blackList(blackList).build())
                .status(CommonCode.SUCCESS.getHttpStatus())
                .result(CommonCode.SUCCESS.getResult())
                .build();
    }

    public BlackListResponse excelUpload(MultipartFile file){

        List<BlackList> list = new ArrayList<>();
        // 파일 존재하지 않는 경우
        if (file.isEmpty()) {
            //Excel 파일을 선택해주세요.
            throw new RestApiException(CommonCode.ERROR.getHttpStatus(), ErrorCode.NOT_EXIT_EXCEL.getMessage() );
        }

        List<Excel> listData = excelUtils.getListData(file);

        // 엑셀 파일내 중복된 데이터 있는지 체크
        if(excelUtils.hasDuplicatesExcel(listData)){
            //중복된 유저 정보가 있습니다.
            throw new RestApiException(CommonCode.ERROR.getHttpStatus(), ErrorCode.DUPLICATE_EXCEL.getMessage() );
        }

        listData.forEach(item->{

                BlackList blackList = new BlackList();

                String user = item.getUser();
                boolean isGuid = true;
                if(item.getType().equals(CommonConstants.NICKNAME)){
                    blackList.setNickname(user);
                    String guid = dynamodbUserService.getNameByGuid(user);
                    if(guid == null || guid.isEmpty()) isGuid = false;
                    blackList.setGuid(guid);
                }else{
                    isGuid = dynamodbUserService.isUser(user);
                    blackList.setGuid(user);
                    String nickName = dynamodbUserService.getGuidByName(user);
                    blackList.setNickname(nickName);
                }

                //adminDB 에 데이터 있는지 체크
                int cnt = blackListMapper.getCountByGuid(blackList.getGuid());
                boolean isBlackUser = dynamodbUserService.isBlockUser(blackList.getGuid());

                if(cnt == 0){
                    if(isBlackUser || !isGuid){
                        blackList.setValidate(false);
                    }else{
                        blackList.setValidate(true);
                    }
                }else if(cnt > 0){
                    blackList.setValidate(false);
//                    throw new RestApiException(CommonCode.ERROR.getHttpStatus(), ErrorCode.ADMINDB_EXIT_ERROR.getMessage());
                }
                list.add(blackList);
            }
        );

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

    public Resource excelDown(String fileName) {
        return resourceLoader.getResource(excelPath + fileName);
    }

    @BusinessProcess(action = LogAction.BLACK_LIST)
    @Transactional(transactionManager = "transactionManager")
    @RequestLog
    public BlackListResponse postBlackList(BlackListRequest blackListRequest){

        // 이용자 제재 상태를 판단하는 로직
        blackListRequest.setStatus(BlackList.STATUSTYPE.WAIT);
        blackListRequest.setCreateBy(CommonUtils.getAdmin().getId());

        //복수 등록일 경우 validation 안함
        if (blackListRequest.getBlackList().size() > 1) {

            blackListRequest.getBlackList().forEach(
                item->{
                    if(item.getGuid() != null){
                        String guid = item.getGuid();
                        if(!dynamodbUserService.isUser(guid)){
                            throw new RestApiException(CommonCode.ERROR.getHttpStatus(), ErrorCode.WARNING_GUID_CHECK.toString());
                        }

                        boolean isBlackUser = dynamodbUserService.isBlockUser(guid);
                        if(isBlackUser){
                            throw new RestApiException(CommonCode.ERROR.getHttpStatus(), ErrorCode.USER_BLOCK_REGIST_DUPLE_WARNING.toString());
                        }
                        blackListRequest.setGuid(guid);
                        blackListRequest.setNickname(item.getNickname());
                        blackListMapper.postBlackList(blackListRequest);
                        logger.info("postBlackList insertBlackList id: {}",blackListRequest.getId());

                    }
                }
            );
        }else{
            //단일일 경우 validation 함
            blackListRequest.getBlackList().forEach(
                    item->{
                        if(item.getGuid() != null){
                            //adminDB 에 데이터 있는지 체크
                            int cnt = blackListMapper.getCountByGuid(item.getGuid());
                            if(cnt > 0){
                                throw new RestApiException(CommonCode.ERROR.getHttpStatus(), ErrorCode.USER_BLOCK_REGIST_DUPLE_WARNING.toString());
                            }
                            if(!dynamodbUserService.isUser(item.getGuid())){
                                throw new RestApiException(CommonCode.ERROR.getHttpStatus(), ErrorCode.WARNING_GUID_CHECK.toString());
                            }

                            boolean isBlackUser = dynamodbUserService.isBlockUser(item.getGuid());
                            if(isBlackUser){
                                throw new RestApiException(CommonCode.ERROR.getHttpStatus(), ErrorCode.USER_BLOCK_REGIST_DUPLE_WARNING.toString());
                            }
                            blackListRequest.setGuid(item.getGuid());
                            blackListRequest.setNickname(dynamodbUserService.getGuidByName(item.getGuid()));
                            blackListMapper.postBlackList(blackListRequest);
                            logger.info("postBlackList insertBlackList id: {}",blackListRequest.getId());

                        }
                    }
            );
        }

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

    }

    @BusinessProcess(action = LogAction.BLACK_LIST)
    @Transactional(transactionManager = "transactionManager")
    @RequestLog
    public BlackListResponse deleteBlackList(BlackListRequest blackListRequest){

        Map<String,Object> map = new HashMap<>();
        blackListRequest.getBlackList().forEach(
                item->{
                    long id = item.getId();
                    BlackList blackList = blackListMapper.getBlackListDetail(id);

                    map.put("id",id);
                    map.put("reason",item.getReason());
                    blackListMapper.deleteBlackList(map);

                    logger.info("deleteBlackList delete id: {}", id);

                    if(dynamodbUserService.isBlockUser(blackList.getGuid()))
                        dynamodbUserService.updateBlockUser(BlackList.STATUSTYPE.EXPIRATION, blackList);
                }
        );

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

    @Transactional(transactionManager = "transactionManager")
    public void updateBlackListStatus(Long id, BlackList.STATUSTYPE status){
        Map<String,Object> map = new HashMap<>();
        map.put("id", id);
        map.put("status", status);

        blackListMapper.updateStatus(map);

        logger.info("updateBlackListStatus status update id: {}, status: {}", id, status.toString());
    }

    public List<BlackList> getScheduleBlackList(){
        return blackListMapper.getScheduleBlackList();
    }

    public void updateScheduleBlockUser(BlackList blockUser, BlackList.STATUSTYPE status){
//        if(status.equals(BlackList.STATUSTYPE.INPROGRESS)){
//            dynamoDBService.updateBlockUserStart(blockUser);
//        }else{
//            dynamoDBService.updateBlockUserEnd(blockUser.getGuid());
//        }
        dynamodbUserService.updateBlockUser(status, blockUser);
    }
}
