package com.bcxin.backend.domain.auth.service.impl;

import com.bcxin.backend.core.exceptions.SaasBadException;
import com.bcxin.backend.domain.auth.dtos.AuthLog;
import com.bcxin.backend.domain.auth.dtos.AuthRequestDto;
import com.bcxin.backend.domain.auth.factory.AuthFactory;
import com.bcxin.backend.domain.models.Result;

import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.stream.Collectors;


@Service
@Slf4j
public abstract class AuthenticationServiceAbstractImpl {

    private static Logger logger = LoggerFactory.getLogger(AuthenticationServiceAbstractImpl.class);

    private final AuthFactory authFactory;

    @Autowired
    @Qualifier("primaryJdbcTemplate")
    protected JdbcTemplate jdbcTemplate;

    public AuthenticationServiceAbstractImpl(AuthFactory authFactory) {
        this.authFactory = authFactory;
    }

    public abstract String findUnAuthSql();

    public Boolean auth() {
        logger.info("-----------------------------------------------实名认证程序开始执行--------------------------------------------------------------");
        //查询出来待认证人员
        try {
            List<AuthRequestDto> authRequestDtos = this.getPendingBgScreenUsers();
            logger.info("查询数据库，待认证人员条数:{};详情=[{}]",
                    authRequestDtos.size(), authRequestDtos.stream().map(ii -> String.format("'%s'", ii.getIdNumber()))
                            .collect(Collectors.joining(","))
            );
            if (!CollectionUtils.isEmpty(authRequestDtos)) {
                Collection<List<AuthRequestDto>> pageAuthRequests = new ArrayList<>();

                List<AuthRequestDto> perPageAuthRequests = null;
                for (int index = 0; index < authRequestDtos.size(); index++) {
                    if (index % 10 == 0) {
                        perPageAuthRequests = new ArrayList<>();

                        pageAuthRequests.add(perPageAuthRequests);
                    }

                    perPageAuthRequests.add(authRequestDtos.get(index));
                }

                pageAuthRequests.parallelStream().forEach(limitAuthUsers -> {
                    Exception lastException = null;
                    try {
                        check(limitAuthUsers);
                    } catch (Exception e) {
                        lastException = e;
                    } finally {
                        logger.error("{}:完成执行实名认证--待认证的人员:{}", (lastException == null ? "成功" : "异常"),
                                limitAuthUsers.stream().map(ii -> String.format("'%s'", ii.getIdNumber()))
                                        .collect(Collectors.joining(",")),
                                lastException);
                    }
                });

                return true;
            } else {
                logger.info("被筛人员列表为空");
                return false;
            }
        } catch (Exception e) {
            logger.error("执行实名认证方法-发生异常:{}", e);
            return false;
        }
    }

    private List<AuthRequestDto> getPendingBgScreenUsers() {
        String sql = findUnAuthSql();
        logger.info("待查询的人员SQL={}", sql);
        return jdbcTemplate.query(sql, BeanPropertyRowMapper.newInstance(AuthRequestDto.class));
    }


    private Result<List<AuthLog>> doExecute(Collection<AuthRequestDto> authRequestDtos) {
        return authFactory.getAuthByType().auth(authRequestDtos);
    }

    protected void check(List<AuthRequestDto> authRequestDtos) {
        try {
            Result<List<AuthLog>> result = this.doExecute(authRequestDtos);
            if (Result.SUCCESS.equals(result.getRetType())) {
                if (result.getData() == null) {
                    throw new SaasBadException(String.format("AuthenticationServiceAbstractImpl:Request interface message returns exception,ErrMsg:%s.", result.getMsg()));
                }
                //获取查询出来的数据
                List<AuthLog> list = result.getData();
                //保存认证结果
                if (list.size() > 0) {
                    this.updateAuthResult(list);
                    logger.info("认证结果为:{}",
                            list.stream().map(ii -> String.format("身份证=%s;结果=%s", ii.getIdNumber(), ii.getAuthResult()))
                                    .collect(Collectors.joining(";"))
                    );
                }
            } else {
                throw new SaasBadException(String.format("AuthenticationServiceAbstractImpl:Request interface failed,ErrMsg:%s.", result.getMsg()));
            }
        } catch (Exception e) {
            logger.error("实名认证出现异常:人员={}",
                    authRequestDtos.stream().map(ii -> ii.getIdNumber()).collect(Collectors.joining(",")), e);
        }
    }

    @Transactional(rollbackFor = Exception.class)
    public void updateAuthResult(List<AuthLog> authlogs) {
        String sql2 =
                "UPDATE bg_screening_users SET `authenticated_status`=?,`authenticated_time`=NOW()," +
                        " `last_modified_time`=NOW(),`authenticated_result`= ? WHERE `idnum` = ?";
        List<Object[]> batchParams = authlogs.stream().map(ii -> {
            return new Object[]{
                    ii.getAuthStatus(), ii.getAuthResult(), ii.getIdNumber()
            };
        }).collect(Collectors.toList());

        jdbcTemplate.batchUpdate(sql2, batchParams);
    }
}
