package com.friday.custody.service.basicService.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.friday.custody.dao.CustodyTenantMappingDao;
import com.friday.custody.dao.TenantInfoDao;
import com.friday.custody.dto.*;
import com.friday.custody.entity.CustodyInterfaceStatisticsEntity;
import com.friday.custody.entity.CustodyTenantMappingEntity;
import com.friday.custody.entity.TablePermissionEntity;
import com.friday.custody.entity.TenantInfoEntity;
import com.friday.custody.enums.RetCodeEnum;
import com.friday.custody.exception.RRException;
import com.friday.custody.req.TenantInfoReq;
import com.friday.custody.service.basicService.TablePermissionService;
import com.friday.custody.service.basicService.TenantInfoService;
import com.friday.custody.utils.PageUtils;
import com.friday.custody.utils.Query;
import com.friday.custody.utils.R;
import com.friday.custody.utils.StrUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;


@Service("tenantInfoService")
@Slf4j
public class TenantInfoServiceImpl extends ServiceImpl<TenantInfoDao, TenantInfoEntity> implements TenantInfoService {

    @Autowired
    TablePermissionService tablePermissionService;
    @Autowired
    private CustodyTenantMappingDao custodyTenantMappingDao;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<TenantInfoEntity> page = this.page(
                new Query<TenantInfoEntity>().getPage(params),
                new QueryWrapper<TenantInfoEntity>()
        );

        return new PageUtils(page);
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public R addTenant(TenantInfoDto dto) {
        try {
            TenantInfoEntity entity = new TenantInfoEntity();
            entity.setTenantName(dto.getTenantName());
            entity.setAccountName(dto.getAccountName());
            entity.setAccountLevel(dto.getAccountLevel());
            entity.setAccountKey(StrUtil.getRandomStr(20));
            entity.setPermissions(JSON.toJSONString(dto.getPermissions()));
            entity.setContactPerson(dto.getContactPerson());
            if (baseMapper.insert(entity) == 1) {
                log.info("账户信息保存成功：{}",JSON.toJSONString(entity));
                return R.ok("用户保存成功！").put("accountKey",entity.getAccountKey());
            }
        } /*catch (SQLIntegrityConstraintViolationException e) {
            log.error("TenantInfoServiceImpl：Exception：", e);
            throw new RRException("该用户已存在！");
        } */ catch (Exception e) {
            log.error("TenantInfoServiceImpl：Exception：", e);
            if (e.getMessage().contains("unique_account")) {
                throw new RRException("该用户已存在！");
            }
        }
        throw new RRException("账号插入失败");
    }




    @Override
    public R<TenantInfoDto> queryByKey(TenantInfoDto dto) {
        try {
            QueryWrapper<TenantInfoEntity> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("tenant_name", dto.getTenantName());
            queryWrapper.eq("account_key", dto.getAccountKey());
            TenantInfoEntity entity = baseMapper.selectOne(queryWrapper);
            if (entity == null) {
                return R.error(RetCodeEnum.RESOURCE_NOT_FOUND.getCode(), "账户不存在或错误，请查证后再试！");
            }
            //需要将entity封装为dto后再返回
            TenantInfoDto result = TenantInfoDto.builder()
                    .id(entity.getId())
                    .tenantName(entity.getTenantName())
                    .accountName(entity.getAccountName())
                    .accountLevel(entity.getAccountLevel())
                    .contactPerson(entity.getContactPerson())
                    .accountKey(entity.getAccountKey())
                    .permissions(JSON.parseArray(entity.getPermissions(), String.class))
                    .createTime(entity.getCreateTime())
                    .updateTime(entity.getUpdateTime())
                    .build();
            R<TenantInfoDto> r = new R<>("查询成功！");
            r.setData(result);
            return r;
        } catch (Exception e) {
            log.error("查询租户信息失败：", e);
            throw new RRException("租户不存在或账密错误！");
        }
    }

    @Override
    public R<List<TenantInfoEntity>> queryAll() {
        try {
            List<TenantInfoEntity> tenantInfoEntities = baseMapper.selectList(new QueryWrapper<>());
            if (ObjectUtils.isEmpty(tenantInfoEntities)) {
                return R.error(RetCodeEnum.RESOURCE_NOT_FOUND.getCode(), "账户不存在或错误，请查证后再试！");
            }
            R<List<TenantInfoEntity>> r = new R<>("查询成功！");
            r.setData(tenantInfoEntities);
            return r;
        } catch (Exception e) {
            log.error("查询租户信息失败：", e);
            throw new RRException("租户不存在或账密错误！");
        }
    }
    @Autowired
    DataDictionaryTrustServiceImpl dataDictionaryTrustService;
    @Override
    public List<TrustNoMonitorDto> queryAllData(String tenantName) {
        List<DataTrustDto> dataTrustDtos = dataDictionaryTrustService.queryAllData();
        HashMap<String, String> hashMap = new HashMap<>();
        for (int i = 0; i < dataTrustDtos.size(); i++) {
            hashMap.put(dataTrustDtos.get(i).getTrustNo(),dataTrustDtos.get(i).getTrustName());
        }
        List<TrustInfoDto> tenantInfoEntities;
        //查询出已经接入的管理人
        List<TrustNoMonitorDto> queryAllAdmin = baseMapper.queryAllAdmin(tenantName);
        //去重
        queryAllAdmin = new ArrayList<>(new HashSet<>(queryAllAdmin));
        for (int i = 0; i < queryAllAdmin.size(); i++) {
            TrustNoMonitorDto trustNoMonitorDto = queryAllAdmin.get(i);
            //String tenantNameNow = trustNoMonitorDto.getAdmin();
            String tenantNameNow = trustNoMonitorDto.getAdminNo();
            //查询出管理人已经接入的托管
            tenantInfoEntities = baseMapper.queryTrustNoData(tenantNameNow);
            //去重
            ArrayList<TrustInfoDto> trustNoMonitorDtos1 = new ArrayList<>(new HashSet<>(tenantInfoEntities));
            //查询该托管已经接入的接口
            for (TrustInfoDto trustInfoDto : trustNoMonitorDtos1) {
                List<ApiDto> tablePermissionDtos = queryTrustNoByAdmin(trustNoMonitorDto.getAdminNo(),trustInfoDto.getTrustNo());
                List<EmailDto> emailDtos = queryHasEmail(trustNoMonitorDto.getAdminNo(),trustInfoDto.getTrustNo());
                trustInfoDto.setEmailList(emailDtos);
                trustInfoDto.setApiList(tablePermissionDtos);
            }
            trustNoMonitorDto.setTrustInfoList(trustNoMonitorDtos1);
            //获取未接入托管
        }
        return queryAllAdmin;
    }
    public List<EmailDto> queryHasEmail(String admin,String trustNo){
        ArrayList<EmailDto> arrayList = new ArrayList<>();
        List<CustodyInterfaceStatisticsEntity> entityList = custodyInterfaceStatisticsService.queryHasEmail(admin,trustNo);
        if (entityList.size()>0){
            for (CustodyInterfaceStatisticsEntity entity : entityList) {
                String interfaceName = entity.getInterfaceName();
                String interfacePath = entity.getInterfacePath();
                arrayList.add(new EmailDto(interfacePath,interfaceName));
            }
            return arrayList;
        }
        return null;
    }
    @Autowired
    InvokeRecordServiceImpl invokeRecordService;
    @Autowired
    CustodyInterfaceStatisticsServiceImpl custodyInterfaceStatisticsService;
    public List<ApiDto> queryTrustNoByAdmin(String admin,String trustNo){
        ArrayList<ApiDto> arrayList = new ArrayList<>();
        for (CustodyInterfaceStatisticsEntity statisticsEntity : custodyInterfaceStatisticsService.queryInterfaceInfo(admin,trustNo)) {
            String interfaceName = statisticsEntity.getInterfaceName();
            String interfacePath = statisticsEntity.getInterfacePath();
            arrayList.add(new ApiDto(interfacePath,interfaceName));
        }
        //invokeRecordService.queryInvokeType(admin,trustNo);
        return arrayList;
    }
    @Override
    public List<TenantInfoMonitorDto> queryAdmin(String trustNo) {
        List<TenantInfoMonitorDto> tenantInfoEntities = baseMapper.queryAdminByTrustNo(trustNo);
        return tenantInfoEntities;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public R addTenantInfos(String tenantName, List<TenantInfoReq> tenantInfoReqs) {
        RRException.isNotTrue(ObjectUtils.isEmpty(tenantInfoReqs),RetCodeEnum.PARAM_ERROR.getCode(),"参数转化失败！");
        //查询所有的表权限
        List<TablePermissionEntity> tablePermissionEntities = tablePermissionService.queryAll();
        List<String> tableNameList = new ArrayList<>();
        tablePermissionEntities.forEach(x ->
                tableNameList.add(x.getTablename()));
        try {
            List tenantEntitys = new ArrayList();
            List<String> nameAndKeyList = new ArrayList<>();
            for (TenantInfoReq req : tenantInfoReqs) {
                String nameAndKey = req.getAdmin() + "," + req.getAccountKey();
                if (ObjectUtils.isNotEmpty(nameAndKeyList) && nameAndKeyList.contains(nameAndKey)){
                    throw new RRException(RetCodeEnum.PARAM_ERROR.getCode(),"同一租户下,accountKey不允许重复！");
                }
                nameAndKeyList.add(nameAndKey) ;
                //校验所传数据
                checkData(req,tableNameList);
                TenantInfoEntity entity = new TenantInfoEntity();
                entity.setTenantName(req.getAdmin());
                entity.setAccountName(StringUtils.isNotBlank(req.getAccountName()) ? req.getAccountName() : tenantName);
                entity.setAccountLevel(0);
                entity.setContactPerson(StringUtils.isNotBlank(req.getContactPerson()) ? req.getContactPerson() : tenantName);
                entity.setAccountKey(req.getAccountKey());
                entity.setPermissions(JSON.toJSONString(req.getPermissionList()));
                entity.setRemark(req.getRemark());
                entity.setCreateTime(new Date());
                entity.setUpdateTime(new Date());
                tenantEntitys.add(entity);
            }
            baseMapper.insertBatch(tenantEntitys);
            return R.ok("创建成功！");
        }catch (RRException rre){
            log.error("批量租户开立异常", rre.getMsg());
            return R.error(RetCodeEnum.PARAM_ERROR.getCode(),rre.getMsg());
        }
        catch (Exception e){
            log.error("创建失败!",e);
            e.getStackTrace();
            if (e.getMessage().contains("unique_account")) {
                throw new RRException("某些用户已存在！");
            }
            return R.error(RetCodeEnum.OPERATION_ERROR.getCode(),"创建失败！");
        }
    }

    @Override
    public boolean isExistsTenant(String admin) {
        List<TenantInfoEntity> entities = baseMapper.queryByAdmin(admin);
        if (CollectionUtils.isNotEmpty(entities)){
            return true;
        }
        return false;
    }

    public int addTenantInfo(String admin) {
        List<String> permissions = Arrays.asList("all");
        String accountName = "未知管理人名称";
        CustodyTenantMappingEntity tenantMappingEntity = custodyTenantMappingDao.queryByAdmin(admin);
        if (tenantMappingEntity != null && StringUtils.isNotEmpty(tenantMappingEntity.getCompanyName())) {
            accountName = tenantMappingEntity.getCompanyName();
        }

        TenantInfoEntity entity = new TenantInfoEntity();
        entity.setTenantName(admin);
        entity.setAccountName(accountName);
        entity.setAccountKey(StrUtil.getRandomStr(20));
        entity.setAccountLevel(0);
        entity.setContactPerson(admin);
        entity.setPermissions(JSON.toJSONString(permissions));
        return baseMapper.insert(entity);
    }


    private void checkData(TenantInfoReq req,List<String> tableNameList) {
        //校验admin是否P+七位数字
        if (req.getAdmin().length() != 8 || !("P").equals(req.getAdmin().substring(0,1)) || !StringUtils.isNumeric(req.getAdmin().substring(1,8))){
            throw new RRException(RetCodeEnum.PARAM_ERROR.getCode(), "admin格式错误，应以P开头，后接7位数字!");
        }
        //校验accountKey包含数字英文 并>=15
        RRException.isNotTrue(!verifyParam(req.getAccountKey()),RetCodeEnum.PARAM_ERROR.getCode(),"accountKey格式错误，应同时包含字母、数字，长度大于等于15位但不超过100位");
        RRException.isNotTrue(StringUtils.isBlank(req.getPermissions()),RetCodeEnum.PARAM_ERROR.getCode(),"permissions不能为空!");
        //校验所传表权限是否正确
        List<String> permissionList = Arrays.asList(req.getPermissions().split(","));
        req.setPermissionList(permissionList);
        if (!permissionList.contains("all")) {
            for (String perssion : permissionList) {
                if (!tableNameList.contains(perssion)) {
                    throw new RRException(RetCodeEnum.PARAM_ERROR.getCode(), "permissions填写错误，包含不存在的表名!");
                }
            }
        }
    }

    /**
     * 校验参数是否包含数字和字母 并超过15个（包含15）
     * @return
     */
    public Boolean verifyParam(String param){
        String regex = "^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]{15,100}$";
        return param.matches(regex);
    }
}