package com.caliverse.admin.domain.service;

import com.caliverse.admin.domain.dao.admin.BlackListMapper;
import com.caliverse.admin.domain.dao.admin.HistoryMapper;
import com.caliverse.admin.domain.entity.BlackList;
import com.caliverse.admin.domain.entity.HISTORYTYPE;
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.code.CommonCode;
import com.caliverse.admin.global.common.code.ErrorCode;
import com.caliverse.admin.global.common.code.SuccessCode;
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 lombok.RequiredArgsConstructor;
import org.json.JSONObject;
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 HistoryMapper historyMapper;
    private final HistoryService historyService;
    private final DynamoDBService dynamoDBService;
    private final DynamodbUserService dynamodbUserService;
    @Value("${caliverse.file}")
    private String excelPath;
    private final ResourceLoader resourceLoader;

    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();
    }

    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<String> listData = excelUtils.getListData(file, 1, 0);

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

        listData.forEach(item->{

                BlackList blackList = new BlackList();
                blackList.setGuid(item);
                //gameDB에서 닉네임, isWhiteUser, isBlackUser 조회
                String nickName = dynamodbUserService.getGuidByName(item);
                if(nickName != ""){
                    blackList.setNickname(nickName);
                }

                //adminDB 에 데이터 있는지 체크
                int cnt = blackListMapper.getCountByGuid(item);
                //gameDB isWhiteUser 값 체크
//                boolean isBlackUser = dynamoDBService.isWhiteOrBlackUser(item);
                boolean isBlackUser = dynamodbUserService.isBlockUser(item);
                boolean isGuid = dynamoDBService.isGuidChecked(item);

//                //guid 검증
//                if(blackAttr.size() == 0){
//                    throw new RestApiException(CommonCode.ERROR.getHttpStatus(), ErrorCode.GUID_CHECK.getMessage());
//                }
//
//                boolean isBlackUser = dynamoDBService.isWhiteOrBlackUser(blackAttr.get("isBlackUser"));
                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);
    }

    @Transactional(transactionManager = "transactionManager")
    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(dynamoDBService.isGuidChecked(guid)){
                            throw new RestApiException(CommonCode.ERROR.getHttpStatus(), ErrorCode.GUID_CHECK.getMessage());
                        }
//                        boolean isBlackUser = dynamoDBService.isWhiteOrBlackUser(guid);
                        boolean isBlackUser = dynamodbUserService.isBlockUser(guid);
                        if(isBlackUser){
                            throw new RestApiException(CommonCode.ERROR.getHttpStatus(), ErrorCode.DYNAMODB_EXIT_ERROR.getMessage());
                        }
                        blackListRequest.setGuid(guid);
                        blackListRequest.setNickname(item.getNickname());
                        blackListMapper.postBlackList(blackListRequest);
                        logger.info("postBlackList insertBlackList: {}",blackListRequest);
                    }
                }
            );
        }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.ADMINDB_EXIT_ERROR.getMessage());
                            }
                            if(dynamoDBService.isGuidChecked(item.getGuid())){
                                throw new RestApiException(CommonCode.ERROR.getHttpStatus(), ErrorCode.GUID_CHECK.getMessage());
                            }
//                            boolean isBlackUser = dynamoDBService.isWhiteOrBlackUser(item.getGuid());
                            boolean isBlackUser = dynamodbUserService.isBlockUser(item.getGuid());
                            if(isBlackUser){
                                throw new RestApiException(CommonCode.ERROR.getHttpStatus(), ErrorCode.DYNAMODB_EXIT_ERROR.getMessage());
                            }
                            blackListRequest.setGuid(item.getGuid());
                            blackListRequest.setNickname(dynamodbUserService.getGuidByName(item.getGuid()));
                            blackListMapper.postBlackList(blackListRequest);
                            logger.info("postBlackList insertBlackList: {}",blackListRequest);
                        }
                    }
            );
        }

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

    }

    @Transactional(transactionManager = "transactionManager")
    public BlackListResponse deleteBlackList(BlackListRequest blackListRequest){

        Map<String,Object> map = new HashMap<>();
        blackListRequest.getBlackList().forEach(
                item->{
                    map.put("id",item.getId());
                    blackListMapper.deleteBlackList(map);

                    //로그 기록
                    BlackList blackList = blackListMapper.getBlackListDetail(Long.valueOf(item.getId()));
                    map.put("adminId",  CommonUtils.getAdmin().getId());
                    map.put("name",  CommonUtils.getAdmin().getName());
                    map.put("mail",  CommonUtils.getAdmin().getEmail());
                    map.put("type", HISTORYTYPE.BLACKLIST_DELETE);
                    JSONObject jsonObject = new JSONObject();
                    jsonObject.put("guid",blackList.getGuid());
                    jsonObject.put("name","");

                    map.put("content",jsonObject.toString());
                    historyMapper.saveLog(map);
                    //dynamoDB char# 테이블에 isBlackUser : false 값을 insert
//                    dynamoDBService.insertUpdateData(blackList.getGuid(),"isBlackUser", false);
                    logger.info("deleteBlackList delete: {}",map);
                    if(blackList.getStatus().equals(BlackList.STATUSTYPE.INPROGRESS))
                        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 BlackListSchedule status update: {}",map);
    }

    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);
    }
}
