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

import com.alibaba.fastjson.JSON;
import com.friday.custody.dto.TenantInfoDto;
import com.friday.custody.enums.RetCodeEnum;
import com.friday.custody.exception.RRException;
import com.friday.custody.req.QueryDataReq;
import com.friday.custody.req.TenantEscrowAuthorizationInfoReq;
import com.friday.custody.req.TenantInfoReq;
import com.friday.custody.service.basicService.DataDictionaryDirectoryService;
import com.friday.custody.service.basicService.impl.PublicDataBasicServiceImpl;
import com.friday.custody.service.basicService.impl.PublicDataDirectoryServiceImpl;
import com.friday.custody.service.basicService.impl.TenantInfoServiceImpl;
import com.friday.custody.service.logicService.DataDictionaryBasicService;
import com.friday.custody.service.logicService.DataProcessService;
import com.friday.custody.service.logicService.LogicExternalService;
import com.friday.custody.service.tenantService.CustodyTenantMappingService;
import com.friday.custody.service.tenantService.TenantService;
import com.friday.custody.utils.R;
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.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.List;
import java.util.Objects;

@Service
@Slf4j
public class LogicExternalServiceImpl implements LogicExternalService {
    @Autowired
    private TenantService tenantService;

    @Resource(name ="dataProcessService")
    private DataProcessService dataProcessService;

    @Resource(name ="dataDictionaryBasicService")
    private DataDictionaryBasicService dataDictionaryBasicService;
    @Autowired
    private DataDictionaryDirectoryService dictionaryDirectoryService;
    @Autowired
    private PublicDataDirectoryServiceImpl publicDataDirectoryService;

    @Resource(name ="publicDataBasicService")
    private PublicDataBasicServiceImpl publicDataBasicService;
    @Autowired
    private CustodyTenantMappingService custodyTenantMappingService;


    @Override
    public R queryData(String tenantName, String accountKey, String type, String params) {
        String errorMsg = "查询失败！";
        try {
            //1 通过租户表查到用户具有的权限
            //1.0 校验传参
            ValidateData(tenantName, accountKey, type);
            TenantInfoDto dto = new TenantInfoDto();
            dto.setTenantName(tenantName);
            dto.setAccountKey(accountKey);
            R<TenantInfoDto> tenantResp = tenantService.queryTenant(dto);
            if (((Integer) tenantResp.get("code")) != RetCodeEnum.SUCCESS.getCode()) {
                log.error("查询数据失败：{},tenant:{}", JSON.toJSONString(tenantResp),tenantName);
                return tenantResp;
            }
            TenantInfoDto tenantInfoDto = tenantResp.getData();
            List<String> tenantPermissions = tenantInfoDto.getPermissions();
            //2 与前端传的type进行比较  看是否具有这个权限
            if (CollectionUtils.isEmpty(tenantPermissions) || !tenantPermissions.contains("all") || tenantPermissions.contains(type)) {
                log.error("租户名：{}，用户：{}，暂无权限查看：{}的数据", tenantInfoDto.getTenantName(), tenantInfoDto.getAccountName(), type);
                return R.error(RetCodeEnum.PERMISSION_DENIED.getCode(), "暂无权限查询！");
            }
            //todo 3 查询数据service 封装返回 此处不需要将dto转为vo
            return dataProcessService.queryData(QueryDataReq.builder()
                    .tenantName(tenantName)
                    .type(type)
                    .params(params)
                    .build());
        } catch (RRException re) {
            log.error("RRException:", re);
            errorMsg = re.getMsg();
        } catch (Exception e) {
            log.error("Exception:", e);
        }
        return R.error(errorMsg);
    }

    private void ValidateData(String tenantName, String accountKey, String type) {
        RRException.isNotTrue(StringUtils.isBlank(tenantName), RetCodeEnum.PARAM_ERROR.getCode(), "租户名不能为空！");
        RRException.isNotTrue(StringUtils.isBlank(accountKey), RetCodeEnum.PARAM_ERROR.getCode(), "用户key不能为空！");
        RRException.isNotTrue(StringUtils.isBlank(type), RetCodeEnum.PARAM_ERROR.getCode(), "type不能为空！");
    }


    @Override
    public R queryDictionary(String tenantName, String type, String accountKey) {
        checkTenantInfo(tenantName, accountKey);
        return dataDictionaryBasicService.queryData(type);
    }

    private void checkTenantInfo(String tenantName, String accountKey) {
        R<TenantInfoDto> tenantInfoDtoR = tenantService.queryTenant(TenantInfoDto.builder().tenantName(tenantName).accountKey(accountKey).build());
        if (Objects.isNull(tenantInfoDtoR.getData())) {
            throw new RRException("租户名或密码错误！");
        }
    }

    @Override
    public R queryDictionaryDirectory(String tenantName, String accountKey,String params) {
        checkTenantInfo(tenantName, accountKey);
        return  dictionaryDirectoryService.queryAll(params);
    }

    @Override
    public R saveTenants(String tenantName, String accountKey, String params) {
        //1.校验参数、判断是否存在当前租户
        checkData(tenantName,accountKey,params);
        log.info("参数params{}：", params);
        R<TenantInfoDto> tenantResp = tenantService.queryTenant(TenantInfoDto.builder().tenantName(tenantName).accountKey(accountKey).build());
        if (((Integer) tenantResp.get("code")) != RetCodeEnum.SUCCESS.getCode()) {
            log.error("租户名或密码错误：{}", JSON.toJSONString(tenantResp));
            return tenantResp;
        }
        //2.判断当前租户permissions权限是否为all* 如果是all才可以添加 否则提示“当前租户无权使用此接口”
        TenantInfoDto tenantInfoDto = tenantResp.getData();
        List<String> tenantPermissions = tenantInfoDto.getPermissions();
        if (CollectionUtils.isEmpty(tenantPermissions) || !tenantPermissions.contains("all")) {
            log.error("租户名：{}，用户：{}，暂无权限查看：{}的数据", tenantInfoDto.getTenantName(), tenantInfoDto.getAccountName());
            return R.error("当前租户无权使用此接口!");
        }
        //添加数据
        return tenantService.addTenants(tenantName,JSON.parseArray(params, TenantInfoReq.class));
    }

    @Override
    public R saveEscrowAuthorizations(String tenantName, String accountKey, String params) {
        try {
            //校验
            checkData(tenantName, accountKey, params);
            log.info("参数params{}：", params);
            //判断当前租户是否存在
            R<TenantInfoDto> tenantResp = tenantService.queryTenant(TenantInfoDto.builder().tenantName(tenantName).accountKey(accountKey).build());
            if (((Integer) tenantResp.get("code")) != RetCodeEnum.SUCCESS.getCode()) {
                log.error("租户名或密码错误：{}", JSON.toJSONString(tenantResp));
                return tenantResp;
            }
            //新增授权
            return tenantService.addEscrowAuthorizations(tenantName, tenantResp.getData(), JSON.parseArray(params, TenantEscrowAuthorizationInfoReq.class));
        }catch (Exception e){
            e.getStackTrace();
            return R.error("授权失败！");
        }
    }
    private void checkData(String tenantName, String accountKey, String params) {
        RRException.isNotTrue(StringUtils.isBlank(tenantName), RetCodeEnum.PARAM_ERROR.getCode(), "租户名不能为空！");
        RRException.isNotTrue(StringUtils.isBlank(accountKey), RetCodeEnum.PARAM_ERROR.getCode(), "用户key不能为空！");
        RRException.isNotTrue(StringUtils.isBlank(params), RetCodeEnum.PARAM_ERROR.getCode(), "参数不能为空！");
    }
    @Override
    public R queryPublicDataDirectory(String tenantName, String accountKey,String params) {
        String errorMsg = "查询公用数据名称失败！";
        try {
            checkPublicTenantInfo(tenantName, accountKey);
            return publicDataDirectoryService.queryList(params);
        }catch (RRException re){
            log.error("查询公共数据名称失败！RRException:", re);
            errorMsg = re.getMsg();
        }catch (Exception e){
            log.error("查询公共数据名称失败！Exception:", e);
        }
        return R.error(errorMsg);
    }

    @Override
    public R queryPublicData(String tenantName, String type, String accountKey, String params) {
        String errorMsg = "查询公用数据失败！";
        try {
            checkPublicTenantInfo(tenantName, accountKey);
            QueryDataReq vo = QueryDataReq.builder()
                    .tenantName(tenantName)
                    .accountKey(accountKey)
                    .type(type)
                    .params(params)
                    .build();
            return publicDataBasicService.queryData(vo);
        }catch (RRException re){
            log.error("查询公共数据失败！RRException:", re);
            errorMsg = re.getMsg();
        }catch (Exception e){
            log.error("查询公共数据失败！Exception:", e);
        }
        return R.error(errorMsg);
    }
@Autowired
TenantInfoServiceImpl tenantInfoService;
    @Override
    public R saveTenantMapping(String admin, String accountKey, String params) {
        String errorMsg = "官网信息保存失败!";
        try {
            //验证admin和accountKey
            checkAdminInfo(admin, accountKey, params);
            //TAIE-17473：新官网的租户和daas中admin映射表【custody_tenant_mapping】相关功能合并到【custody_tenant_info】。
            //暂时不合并
            //return tenantInfoService.saveTenantMapping(params);
            return custodyTenantMappingService.saveTenantMapping(params);
        }catch (RRException re) {
            log.error("保存官网信息失败! RRException:", re);
            errorMsg = re.getMsg();
        } catch (Exception e) {
            log.error("保存官网信息失败! Exception:", e);
        }
        return R.error(errorMsg);
    }

    @Override
    public R queryTenantMapping(String admin, String accountKey, String params) {
        String errorMsg = "查询失败!";
        try {
            //验证admin和accountKey
            checkAdminInfo(admin, accountKey, params);
            return custodyTenantMappingService.queryTenantMapping(params);
        }catch (RRException re) {
            log.error("查询官网租户信息失败! RRException:", re);
            errorMsg = re.getMsg();
        } catch (Exception e) {
            log.error("查询官网租户信息失败! Exception:", e);
        }
        return R.error(errorMsg);
    }
    //调用查询官网信息需固定判断admin和accountKey
    public static String TENANT_MAPING_ADMIN = "admin";
    public static String TENANT_MAPING_ACCOUNTKEY = "af48b6f53cbd45b79c41774a3c27df6a";
    private void checkAdminInfo(String admin, String accountKey, String tenant) {
        RRException.isNotTrue(StringUtils.isBlank(admin), RetCodeEnum.PARAM_ERROR.getCode(), "租户名不能为空！");
        RRException.isNotTrue(StringUtils.isBlank(accountKey), RetCodeEnum.PARAM_ERROR.getCode(), "用户key不能为空！");
        RRException.isNotTrue(!TENANT_MAPING_ADMIN.equals(admin) || !TENANT_MAPING_ACCOUNTKEY.equals(accountKey),
                RetCodeEnum.PARAM_ERROR.getCode(), "用户名或密码错误！");
        RRException.isNotTrue(StringUtils.isBlank(tenant), RetCodeEnum.PARAM_ERROR.getCode(), "请求参数不能为空!");
    }

    private void checkPublicTenantInfo(String tenantName, String accountKey) {
        RRException.isNotTrue(StringUtils.isBlank(tenantName), RetCodeEnum.PARAM_ERROR.getCode(), "租户名不能为空！");
        RRException.isNotTrue(StringUtils.isBlank(accountKey), RetCodeEnum.PARAM_ERROR.getCode(), "用户key不能为空！");
        RRException.isNotTrue(!"H0000001".equals(tenantName), RetCodeEnum.PARAM_ERROR.getCode(), "请使用公用租户账号和密码！");
        R<TenantInfoDto> tenantInfoDtoR = tenantService.queryTenant(TenantInfoDto.builder().tenantName(tenantName).accountKey(accountKey).build());
        if (Objects.isNull(tenantInfoDtoR.getData())) {
            throw new RRException("租户名或密码错误！");
        }
    }

}
