package cn.superdesk.uniorder.dubbo.provider.sys;

import cn.hutool.core.util.ObjectUtil;
import cn.superdesk.uniorder.common.enums.login.SysLoginMethodEnum;
import cn.superdesk.uniorder.common.enums.login.SysLoginTypeEnum;
import cn.superdesk.uniorder.common.exception.UnifiedOrderRuntimeException;
import cn.superdesk.uniorder.common.json.AnJsonUtils;
import cn.superdesk.uniorder.common.mq.redis.constants.BaseRedisConf;
import cn.superdesk.uniorder.common.mq.redis.service.RedisManager;
import cn.superdesk.uniorder.common.numerical.*;
import cn.superdesk.uniorder.common.rest.response.R;
import cn.superdesk.uniorder.common.security.JwtUtil;
import cn.superdesk.uniorder.common.security.dto.LoginSysUser;
import cn.superdesk.uniorder.common.security.dto.TokenVo;
import cn.superdesk.uniorder.dao.entity.organisation.SysCompany;
import cn.superdesk.uniorder.dao.entity.sys.SysUser;
import cn.superdesk.uniorder.dao.entity.sys.SysUserOrderSourcetypeKey;
import cn.superdesk.uniorder.dao.entity.sys.role.SysRoleExtData;
import cn.superdesk.uniorder.dao.entity.sys.role.SysRoleExtDataSample;
import cn.superdesk.uniorder.dto.param.organisation.UnifiedSupplierQueryCriteria;
import cn.superdesk.uniorder.dto.param.system.SysUserQueryCriteria;
import cn.superdesk.uniorder.dto.vo._function.select.SelectOptionOrg;
import cn.superdesk.uniorder.dto.vo._function.select.SelectOptionSysUser;
import cn.superdesk.uniorder.dto.vo._function.select.SelectOptionVirt;
import cn.superdesk.uniorder.dto.vo._superdeskapp.jwt.SupperdeskAppTokenUser;
import cn.superdesk.uniorder.dto.vo.organisation.UnifiedSupplierVo;
import cn.superdesk.uniorder.dto.vo.sys.SysUserView;
import cn.superdesk.uniorder.dto.vo.sys.SysUserVo;
import cn.superdesk.uniorder.dubbo.facade.sys.DubboSysUserService;
import cn.superdesk.uniorder.service._permission.PermissionService;
import cn.superdesk.uniorder.service.common.UnifiedUserlogService;
import cn.superdesk.uniorder.service.organisation.SysSupplierService;
import cn.superdesk.uniorder.service.sys.SysUserService;
import cn.superdesk.uniorder.service.sys.role.SysMenuOpenApiService;
import cn.superdesk.uniorder.service.sys.role.SysRoleExtDataSampleService;
import cn.superdesk.uniorder.service.sys.role.SysRoleExtDataService;
import com.alibaba.dubbo.config.annotation.Service;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
@Service(version = "1.0.0", retries = -1, timeout = 10000)
public class DubboSysUserServiceImpl implements DubboSysUserService {

	@Autowired
	private SysUserService     sysUserService;
	@Autowired
	private SysSupplierService unifiedSupplierService;

	@Autowired
	private UnifiedUserlogService unifiedUserlogService;

	@Autowired
	private SysRoleExtDataService       sysRoleExtDataService;
	@Autowired
	private SysRoleExtDataSampleService sysRoleExtDataSampleService;

	@Autowired
	private SysMenuOpenApiService sysMenuOpenApiService;
	@Resource
	private PermissionService     permissionService;

	//	@Resource
//	private RedisService redisService;
	@Resource
	private RedisManager redisManager;
//	@Resource
//	private RedisUtil    redisUtil;


	public SysUserVo userLoginBySupperDeskUniOrderBackEndFacade(String username, String password) throws UnifiedOrderRuntimeException {

		// 执行通用登陆
		SysUserVo result = userLoginCommon(username, password, SysLoginMethodEnum.统一订单后台账号, SysLoginTypeEnum.统一订单);
		return result;
	}

	/***
	 * 服务之窗 单点登陆
	 * @param supperdeskAppTokenUser
	 * @return
	 */
	@Override
	public SysUserVo userLoginBySupperDeskUniServiceTokenFacade(SupperdeskAppTokenUser supperdeskAppTokenUser) {

		// 实际 先通过 saleId saleName 查对对映的 后台帐号密码
		SysUser sysUser = sysUserService.getSysUser4SupperDeskUniService(supperdeskAppTokenUser);

		log.info("关键 {}", AnJsonUtils.toJson(sysUser));

		if (null != sysUser) {

			// 实际调用的登陆
			return userLoginBySupperDeskUniServiceToken(sysUser.getUserName(), sysUser.getUserPassword(), supperdeskAppTokenUser);
		}
		// 供应商账号 不存在 返回空 不过只要供应存在 , 就会去建帐号 这个逻辑好像是多余的
		else {
			return null;
		}
	}

	@Override
	public SysUserVo userLoginBySupperDeskUniServiceToken(String username, String password, SupperdeskAppTokenUser userToken) {

		// 执行通用登陆
		SysUserVo result = userLoginCommon(username, password, SysLoginMethodEnum.服务之窗后台账号, SysLoginTypeEnum.服务之窗);
		return result;
	}


	/**
	 * 商城 供应商登陆
	 *
	 * @param conditions
	 * @return
	 */
	public SysUserVo userLoginBySupperDeskUniMallSupplierFacade(/*saleId saleName*/Map<String, Object> conditions) {

		//		param
//		{
//			"conditions" : {
//				"saleId" : 1,
//				"saleName" : "前台优选"
//			}
//		}

		log.info("userLoginBySupplier conditions {}", AnJsonUtils.toJson(conditions));

		if (ObjectUtil.isNull(conditions.get("saleId"))) {
			return null;
		}

		if (ObjectUtil.isNull(conditions.get("saleName"))) {
			return null;
		}


		Long   saleId   = AnLongUtils.getLong(conditions.get("saleId"));
		String saleName = AnStringUtils.getString(conditions.get("saleName"));


//		private Integer enabled = 1;
//		private String  serviceNo;

//		conditions.put("enabled", 1);
//		conditions.put("serviceNo", "");


//saleId
//saleName
//serviceNo

		// 过来的信息 先去 表 密码写死
//		SELECT * FROM `sys_user`

//		如果没有的话 要生成账号

//		UnifiedSupplier unifiedSupplier = new UnifiedSupplier();
//
//		unifiedSupplier.setSaleId();
//		unifiedSupplier.setSaleName();


		// 传入的只有 saleId saleName 先去 unifiedSupplier 查一下 有没有这个供应商
		List<UnifiedSupplierVo> supplierList = unifiedSupplierService.findByCriteria(
				UnifiedSupplierQueryCriteria
						.builder()
						.saleId(saleId)
						.saleName(saleName)
						.build()
		);
		log.info(AnJsonUtils.toJson(supplierList));

		// 供应商 不存在 返回空
		if (AnCollectionUtils.isEmpty(supplierList)) {
			return null;
		} else {

			// debug
//			return userLogin("linjy", "Aa123456");

			// 如果有这个供应商 ,再去看一下 帐号

			// 按规则 产生 用户信息 先定义为 规则 username 为 {outSaleName} ; password 为 {outSaleId}_{outSaleName}

			// 这个信息去查 账号存在不?
			// |---- 在 ->
			// |---- 不在 -> 去建个

			// 实际 先通过 saleId saleName 查对对映的 后台帐号密码
			SysUser sysUser = sysUserService.getSysUser4SupperDeskUniMallSupplier(saleId, saleName);
			log.info("关键 {}", AnJsonUtils.toJson(sysUser));

			if (null != sysUser) {

				// 实际调用的登陆
				return userLoginBySupperDeskUniMallSupplier(saleId, saleName, sysUser);
			}
			// 供应商账号 不存在 返回空 不过只要供应存在 , 就会去建帐号 这个逻辑好像是多余的
			else {
				return null;
			}
		}
	}

	@Override
	public SysUserVo userLoginBySupperDeskUniMallSupplier(Long saleId, String saleName, SysUser sysUser) throws UnifiedOrderRuntimeException {

		// 执行通用登陆
		SysUserVo result = userLoginCommon(sysUser.getUserName(), sysUser.getUserPassword(), SysLoginMethodEnum.商城供应商账号, SysLoginTypeEnum.福利商城_侨城汇);

		redisManager.setTokenInfoAdditionalOutSaleCache(saleId, saleName, sysUser.getUserName());

		return result;
	}


	/**
	 * mark by linjinyu 20201110 改为兼容登陆
	 *
	 * @param username
	 * @param password
	 * @param sysLoginTypeEnum
	 * @return
	 * @throws UnifiedOrderRuntimeException
	 */
	@Override
	public SysUserVo userLoginCommon(String username, String password, SysLoginMethodEnum sysLoginMethodEnum, SysLoginTypeEnum sysLoginTypeEnum) throws UnifiedOrderRuntimeException {

		log.info("\n\n\n\n共用的 userLogin \nusername : {}\npassword : {}\n\n\n\n", username, password);

//		SysUser sysUser = new SysUser();
//		sysUser.setUserName(username);
//		sysUser.setUserPassword(password);

		Map<String, Object> queryMap = new HashMap<>();
		queryMap.put("username", username);
		queryMap.put("password", password);
		List<SysUser> checkSysUserList = sysUserService.findAll(queryMap);

		log.info("userLogin.checkSysUserList : \n{}", AnJsonUtils.toPrettyJson(checkSysUserList));

		if (AnCollectionUtils.isEmpty(checkSysUserList)) {
			return null;
		}


		SysUser   sysUser    = checkSysUserList.get(0);
		SysUserVo responseVo = new SysUserVo();

		// 问题  mark by linjinyu at 20210312
//        BeanUtils.copyProperties(sysUser, responseVo);

		responseVo = AnBeanUtils.copy(sysUser, SysUserVo.class);

		if (sysLoginMethodEnum == SysLoginMethodEnum.商城供应商账号 && sysLoginTypeEnum == SysLoginTypeEnum.福利商城_侨城汇) {

			String[] splitStr = sysUser.getUserPassword().split("_");

			responseVo.setOutSaleId(AnLongUtils.getLong(splitStr[0]));
		}

		log.info("\n\nuserLogin : \n|---- SysUser\n{}\n|---- SysUserVo\n{}\n\n\n\n", AnJsonUtils.toPrettyJson(sysUser), AnJsonUtils.toPrettyJson(responseVo));

		/****************************************** 角色 权限 菜单 start  ******************************************/
		// TODO 可以加速一下

		/****************************************** 角色 权限 菜单   end  ******************************************/

		/****************************************** 角色 权限 数据 start  ******************************************/

		String sysOrgIds    = "";
		String sysOrgNames  = "";
		String sysVirtIds   = "";
		String sysVirtNames = "";

		String outOrgIds    = "";
		String outOrgNames  = "";
		String outVirtIds   = "";
		String outVirtNames = "";

		String outSaleId   = "";
		String outSaleName = "";

		List<SelectOptionOrg>  selectPermOrg  = new ArrayList<>();
		List<SelectOptionVirt> selectPermVirt = new ArrayList<>();


		List<SysRoleExtDataSample> sysRoleExtDataSampleList = new ArrayList<>();

		log.info("当前用户 数据权限角色 id : {}", sysUser.getSysRoleExtDataId());

		// TODO 有空的情况 现在 空的情况 默认是 没有 受限

		SysRoleExtData sysRoleExtData = sysRoleExtDataService.findSysRoleExtDataById(sysUser.getSysRoleExtDataId());

		// 不为空的情况
		if (null != sysRoleExtData) {

			// 不为空时才去做
			if (StringUtils.isNotBlank(sysRoleExtData.getSysRoleExtSampleIds())) {

				sysRoleExtDataSampleList = sysRoleExtDataSampleService.findSysRoleExtDataSampleBySysRoleExtDataId(AnStringUtils.stringArrayConvertToLongList(sysRoleExtData.getSysRoleExtSampleIds(), ","));

				log.info(AnJsonUtils.toPrettyJson(sysRoleExtDataSampleList));

				if (AnCollectionUtils.isNotEmpty(sysRoleExtDataSampleList)) {

					StringBuffer outOrgIdsBuf  = new StringBuffer();
					StringBuffer outVirtIdsBuf = new StringBuffer();

					StringBuffer sysOrgIdsBuf  = new StringBuffer();
					StringBuffer sysVirtIdsBuf = new StringBuffer();

					for (SysRoleExtDataSample sample : sysRoleExtDataSampleList) {

						if (StringUtils.isNotBlank(outOrgIdsBuf)) {
							outOrgIdsBuf.append(",").append(sample.getOutOrgId());
						} else {
							outOrgIdsBuf.append(sample.getOutOrgId());
						}

						log.info("outOrgIdsBuf : {}", outOrgIdsBuf.toString());

						if (StringUtils.isNotBlank(outVirtIdsBuf)) {
							outVirtIdsBuf.append(",").append(sample.getOutVirtIds());
						} else {
							outVirtIdsBuf.append(sample.getOutVirtIds());
						}

						log.info("outVirtIdsBuf : {}", outVirtIdsBuf.toString());

						if (StringUtils.isNotBlank(sysOrgIdsBuf)) {
							sysOrgIdsBuf.append(",").append(sample.getSysOrgId());
						} else {
							sysOrgIdsBuf.append(sample.getSysOrgId());
						}

						log.info("sysOrgIdsBuf : {}", sysOrgIdsBuf.toString());

						if (StringUtils.isNotBlank(sysVirtIdsBuf)) {
							sysVirtIdsBuf.append(",").append(sample.getSysVirtIds());
						} else {
							sysVirtIdsBuf.append(sample.getSysVirtIds());
						}

						log.info("sysVirtIdsBuf : {}", sysVirtIdsBuf.toString());
					}

					outOrgIds = outOrgIdsBuf.toString();
					outVirtIds = outVirtIdsBuf.toString();

					sysOrgIds = sysOrgIdsBuf.toString();
					sysVirtIds = sysVirtIdsBuf.toString();


				}
			}
		}

		log.info("sysOrgIds    :{}", sysOrgIds);
		log.info("sysOrgNames  :{}", sysOrgNames);
		log.info("sysVirtIds   :{}", sysVirtIds);
		log.info("sysVirtNames :{}", sysVirtNames);
		log.info("outOrgIds    :{}", outOrgIds);
		log.info("outOrgNames  :{}", outOrgNames);
		log.info("outVirtIds   :{}", outVirtIds);
		log.info("outVirtNames :{}", outVirtNames);


		// 处理 select 数据 start
		List<Long> outOrgIdsDistinct  = AnStringUtils.stringArrayConvertToLongList(outOrgIds, ",");
		List<Long> outVirtIdsDistinct = AnStringUtils.stringArrayConvertToLongList(outVirtIds, ",");

		if (StringUtils.isNotBlank(outOrgIds) && AnCollectionUtils.isNotEmpty(outOrgIdsDistinct)) {
			selectPermOrg = permissionService.convertSelectPermOrg(outOrgIdsDistinct);
		}
		if (StringUtils.isNotBlank(outVirtIds) && AnCollectionUtils.isNotEmpty(outVirtIdsDistinct)) {
			selectPermVirt = permissionService.convertSelectPermVirt(outVirtIdsDistinct);
		}


		log.info("outOrgIdsDistinct    :{}", AnStringUtils.longListConvertToString(outOrgIdsDistinct));
		log.info("outVirtIdsDistinct   :{}", AnStringUtils.longListConvertToString(outVirtIdsDistinct));

		// 处理 select 数据   end


		/****************************************** 角色 权限 数据   end  ******************************************/


		// create token
		TokenVo token = JwtUtil.createToken(
				responseVo.getId().toString(),
				responseVo.getUserName(),
				responseVo.getFullname(),
				responseVo.getRoleId().toString(),
				null,
				null,
				outSaleId,
				BaseRedisConf.TOKEN_EXPIRE_TIME,
				sysLoginTypeEnum.getKey()
		);

		responseVo.setToken(token.getToken());

		// create refresh token
		TokenVo refreshToken = JwtUtil.createToken(
				responseVo.getId().toString(),
				responseVo.getUserName(),
				responseVo.getFullname(),
				responseVo.getRoleId().toString(),
				null,
				null,
				outSaleId,
				BaseRedisConf.REFRESH_TOKEN_EXPIRE_TIME,
				sysLoginTypeEnum.getKey()
		);
		responseVo.setRefreshToken(refreshToken.getToken());

		// save token in redis
		String createTime = AnDateHelper.formatDateToStr(token.getCreateTime());

		Map<String, String> mapValueForRedis = Maps.newHashMap();


		mapValueForRedis.put("userId", responseVo.getId().toString());
		mapValueForRedis.put("userName", responseVo.getUserName());
		mapValueForRedis.put("fullname", responseVo.getFullname());
		mapValueForRedis.put("token", responseVo.getToken());
		mapValueForRedis.put("refreshToken", responseVo.getRefreshToken());
		mapValueForRedis.put("createTime", createTime);
		mapValueForRedis.put("updateTime", createTime);

		/****************************************** 角色 菜单按扭权限 start  ******************************************/
		mapValueForRedis.put("roleId", responseVo.getRoleId().toString());
		/****************************************** 角色 菜单按扭权限   end  ******************************************/

		/****************************************** 角色 数据权限 start  ******************************************/
		mapValueForRedis.put("sysOrgIds", sysOrgIds);
		mapValueForRedis.put("sysOrgNames", sysOrgNames);
		mapValueForRedis.put("sysVirtIds", sysVirtIds);
		mapValueForRedis.put("sysVirtNames", sysVirtNames);

//		mapValueForRedis.put("outOrgIds", outOrgIds);
		mapValueForRedis.put("outOrgIds", AnStringUtils.longListConvertToString(outOrgIdsDistinct));
		mapValueForRedis.put("outOrgNames", outOrgNames);
//		mapValueForRedis.put("outVirtIds", outVirtIds);
		mapValueForRedis.put("outVirtIds", AnStringUtils.longListConvertToString(outVirtIdsDistinct));
		mapValueForRedis.put("outVirtNames", outVirtNames);

		mapValueForRedis.put("selectPermOrg", AnJsonUtils.toJson(selectPermOrg));
		mapValueForRedis.put("selectPermVirt", AnJsonUtils.toJson(selectPermVirt));

		mapValueForRedis.put("sysRoleExtData", AnJsonUtils.toJson(sysRoleExtData));
		mapValueForRedis.put("sysRoleExtDataSampleList", AnJsonUtils.toJson(sysRoleExtDataSampleList));
		/****************************************** 角色 数据权限   end  ******************************************/

		/****************************************** 第三方 start ******************************************/


		/****************************************** 第三方   end ******************************************/


		mapValueForRedis.put("expireTime", AnDateHelper.formatDateToStr(token.getExpireTime()));
		mapValueForRedis.put("outLogin", AnStringUtils.getString(sysLoginTypeEnum.getKey()));

		redisManager.setTokenInfoCache(mapValueForRedis, responseVo.getUserName());

		/****************************************** 基于api地址的权限 mark by linjinyu at 20211101 start ******************************************/

		Map<String, String> permMenuOpenApiMap = sysMenuOpenApiService.getPerm2MapStringEntityString();
		redisManager.setPermissionOpenApiCache(permMenuOpenApiMap, responseVo.getUserName());

		/****************************************** 基于api地址的权限 mark by linjinyu at 20211101 start ******************************************/


		return responseVo;

	}


//	private SysUser getSysUser4Supplier(Long outSaleId, String outSaleName) {
//
//		return sysUserService.getSysUser4Supplier(outSaleId, outSaleName);
//	}


	@Override
	public R<List<SysUserView>> findAllPage(SysUserQueryCriteria queryCriteria) {

		return sysUserService.findAllPage(queryCriteria);
	}

	@Override
	public SysUser add(SysUser sysUser, List<SysUserOrderSourcetypeKey> sysUserOrderSourcetypeKeys) {

		return sysUserService.addTran(sysUser, sysUserOrderSourcetypeKeys);
	}

	@Override
	public void edit(SysUser user, List<SysUserOrderSourcetypeKey> ls) {

		sysUserService.updateObjTran(user, ls);
	}

	@Override
	public void delete(Long id) {

		sysUserService.deleteObj(id);
	}

	@Override
	public int opPhysicsDelete(Long id, LoginSysUser loginSysUser) {
		return sysUserService.opPhysicsDelete(id, loginSysUser);
	}

	@Override
	public int opLogicalDelete(Long id, LoginSysUser loginSysUser) {
		return sysUserService.opLogicalDelete(id, loginSysUser);
	}


	@Override
	public List<SelectOptionSysUser> findAll(Map<String, Object> params) {

		List<SysUser>             sysUserList = sysUserService.findAll(params);
		List<SelectOptionSysUser> resultList  = AnConvertBeanUtil.copyListBeanToList(sysUserList, SelectOptionSysUser.class);
		return resultList;
	}


	@Override
	public List<SysUser> findBySysUserIds(List<Long> sysUserIds) {
		return sysUserService.findBySysUserIds(sysUserIds);
	}


	/****************************************** 工具方法 sysUserIds 推导 start ******************************************/

	@Override
	public List<String> convertSysUserIds2FullName(List<Long> sysUserIds) {
		return sysUserService.convertSysUserIds2FullName(sysUserIds);
	}

	@Override
	public Map<Long, String> convertSysUserIds2MapSysUserId2FullName(List<Long> sysUserIds) {
		return sysUserService.convertSysUserIds2MapSysUserId2FullName(sysUserIds);
	}

	@Override
	public Map<Long, SysUser> convertSysUserIds2MapSysUserId2Entity(List<Long> sysUserIds) {
		return sysUserService.convertSysUserIds2MapSysUserId2Entity(sysUserIds);
	}


	/****************************************** 工具方法 sysUserIds 推导   end ******************************************/


	@Override
	public SysCompany getSysCompany(Long id) {

		return sysUserService.getSysCompany(id);
	}


//	@Override
//	public SysUserVO refreshToken(String userId) {
//
//		return sysUserService.refreshToken(userId);
//	}
//
//	@Override
//	public int addModel(SysUser model) {
//
//
//		return sysUserService.insertSelective(model);
//	}

//	@Override
//	public int addSave(SysUserModify modify) {
//
//		SysUser user = AnConvertBeanUtil.copyBean(modify, SysUser.class);
//		return sysUserService.insertSelective(user);
//	}
//
//	@Override
//	public SysUser findById(String userId) {
//
//		return sysUserService.selectByPrimaryKey(userId);
//	}
//
//	@Override
//	public int updateObj(SysUserModify modify) {
//
//		SysUser user = AnConvertBeanUtil.copyBean(modify, SysUser.class);
//		return sysUserService.updateByPrimaryKeySelective(user);
//	}
//
//	@Override
//	public SysUserVO loginByToken(String token) throws MyException{
//		return sysUserService.loginByToken(token);
//	}
//
//
//	@Override
//	public ResponseResult<List<SysUserQueryVO>> listSysUser(SysUserParamsVO vo) throws MyException {
//		return sysUserService.listSysUser(vo);
//	}
//
//	@Override
//	public ResponseResult<SysUserEditVO> getSysUser(SysUserParamsVO vo) throws MyException {
//		return sysUserService.getSysUser(vo);
//	}
//
//	@Override
//	public SysUser findbyContact(String contactNumber) {
//
//		return sysUserService.findbyContact(contactNumber);
//	}


}
