/*
 *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *
 *  Redistributions of source code must retain the above copyright notice,
 *  this list of conditions and the following disclaimer.
 *  Redistributions in binary form must reproduce the above copyright
 *  notice, this list of conditions and the following disclaimer in the
 *  documentation and/or other materials provided with the distribution.
 *  Neither the name of the dreamlu.net developer nor the names of its
 *  contributors may be used to endorse or promote products derived from
 *  this software without specific prior written permission.
 *  Author: Chill 庄骞 (smallchill@163.com)
 */
package org.springblade.estate.service.impl;

import org.apache.commons.lang.StringUtils;
import org.springblade.common.constant.CommonConstant;
import org.springblade.common.constant.OperationConstant;
import org.springblade.community.entity.Room;
import org.springblade.community.feign.ICommunityClient;
import org.springblade.community.feign.IRoomClient;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.Func;
import org.springblade.core.tool.utils.StringUtil;
import org.springblade.device.dto.DispatchTask;
import org.springblade.device.dto.UserInfoDto;
import org.springblade.device.feign.IDoorDeviceClient;
import org.springblade.device.vo.DoorDeviceVO;
import org.springblade.estate.dto.ApplyUserDTO;
import org.springblade.estate.dto.UserAccessPermissionsDTO;
import org.springblade.estate.entity.ApplyUser;
import org.springblade.estate.service.IUserAccessPermissionsService;
import org.springblade.estate.vo.ApplyUserVO;
import org.springblade.estate.mapper.ApplyUserMapper;
import org.springblade.estate.service.IApplyUserService;
import org.springblade.core.mp.base.BaseServiceImpl;
import org.springblade.person.entity.HouseUser;
import org.springblade.person.entity.Member;
import org.springblade.person.feign.IHouseUserClient;
import org.springblade.person.feign.IMemberClient;
import org.springblade.system.expand.entity.Conf;
import org.springblade.system.expand.feign.IConfClient;
import org.springblade.system.feign.IDictBizClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import org.springframework.transaction.annotation.Transactional;

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

/**
 * 申请用户表---房屋成员 服务实现类
 *
 * @author BladeX
 * @since 2021-04-23
 */
@Service
public class ApplyUserServiceImpl extends BaseServiceImpl<ApplyUserMapper, ApplyUser> implements IApplyUserService {

	private final IMemberClient memberClient;
	private final IHouseUserClient houseUserClient;
	private final ICommunityClient communityClient;
	private final IConfClient confClient;
	private final IDoorDeviceClient doorDeviceClient;
	private final IRoomClient roomClient;
	private final IUserAccessPermissionsService userAccessPermissionsService;
	private final IDictBizClient dictBizClient;


	@Autowired
	public ApplyUserServiceImpl(IMemberClient memberClient, IHouseUserClient houseUserClient
		, ICommunityClient communityClient, IConfClient confClient, IDoorDeviceClient doorDeviceClient, IRoomClient roomClient, IUserAccessPermissionsService userAccessPermissionsService, IDictBizClient dictBizClient) {
		this.memberClient = memberClient;
		this.houseUserClient = houseUserClient;
		this.communityClient = communityClient;
		this.confClient = confClient;
		this.doorDeviceClient = doorDeviceClient;
		this.roomClient = roomClient;
		this.userAccessPermissionsService = userAccessPermissionsService;
		this.dictBizClient = dictBizClient;
	}

	@Override
	public IPage<ApplyUserVO> selectApplyUserPage(IPage<ApplyUserVO> page, ApplyUserVO applyUser) {
		return page.setRecords(baseMapper.selectApplyUserPage(page, applyUser));
	}

	@Override
	@Transactional
	public boolean authentication(ApplyUser applyUser) {
		//添加住户申请记录
		applyUser.setFaceUrl(confClient.removePrefix(applyUser.getFaceUrl()));
		applyUser.setEntryImgUri(confClient.removePrefix(applyUser.getEntryImgUri()));
		applyUser.setPassportImgUri(confClient.removePrefix(applyUser.getPassportImgUri()));
		boolean result = this.save(applyUser);
		if (result) {
			//更新会员状态
			Member member = new Member();
			member.setId(applyUser.getMemberId());
			//认证状态：{ 0：未认证，1：待审审核，2：已认证 }
			member.setState(CommonConstant.MemberAuditStatus.wait.getValue());
			member.setIdcard(applyUser.getIdCard());
			//修改会员状态---待审核
			result = this.memberClient.update(member);
		}
		return result;

	}

//	@Override
//	@Transactional
	public boolean addApplyUserForFamilyBak(ApplyUser applyUser) {
		applyUser.setFaceUrl(confClient.removePrefix(applyUser.getFaceUrl()));
		applyUser.setEntryImgUri(confClient.removePrefix(applyUser.getEntryImgUri()));
		applyUser.setPassportImgUri(confClient.removePrefix(applyUser.getPassportImgUri()));
		Boolean result = false;
		if (this.save(applyUser)) {
			HouseUser oldUser = null;
			if (applyUser.getUserId() != null) {//编辑
				HouseUser searchUser = new HouseUser();
				searchUser.setId(applyUser.getUserId());
				oldUser = this.houseUserClient.detail(searchUser);
			}

			HouseUser houseUser = null;
			//存在住户信息

			if (oldUser != null) {
				boolean isUpdate = false;
				houseUser = new HouseUser();
				houseUser.setFaceEnable(oldUser.getFaceEnable());
				houseUser.setId(oldUser.getId());
				//替换身份
				if (applyUser.getType() != null && !applyUser.getType().equals(oldUser.getType())) {
					houseUser.setType(applyUser.getType());
					isUpdate = true;
				}
				//替换手机
				if (StringUtils.isNotBlank(applyUser.getPhone()) && !applyUser.getPhone().equals(oldUser.getPhone())) {
					houseUser.setPhone(applyUser.getPhone());
					isUpdate = true;
				}
				//替换身份证
				if (StringUtils.isNotBlank(applyUser.getIdCard()) && !applyUser.getIdCard().equals(oldUser.getIdCard())) {
					houseUser.setIdCard(applyUser.getIdCard());
					isUpdate = true;
				}
				//人脸替换
				if (StringUtils.isNotBlank(applyUser.getFaceUrl())) {
					houseUser.setFaceUrl(applyUser.getFaceUrl());
					houseUser.setImageMd5(applyUser.getImageMd5());
					if (oldUser.getAuditStatus() == null || oldUser.getAuditStatus() != 1) {
						houseUser.setAuditStatus(1);
					}
					if (oldUser.getFaceEnable() == null || oldUser.getFaceEnable() == -1) {
						houseUser.setFaceEnable(0);
					}
					isUpdate = true;
				}
				//房间
				if (applyUser.getRoomId() != null && !applyUser.getRoomId().equals(oldUser.getRoomId())) {
					Room room = roomClient.getById(applyUser.getRoomId());
					houseUser.setRoomId(applyUser.getRoomId());
					houseUser.setFloorId(room.getFloorId());
					houseUser.setFloorName(room.getFloorName());
					isUpdate = true;
				}
				//性别
				if (applyUser.getSex() != null && !applyUser.getSex().equals(oldUser.getSex())) {
					houseUser.setSex(applyUser.getSex());
					isUpdate = true;
				}
				//国籍
				if (applyUser.getNationality() != null && !applyUser.getNationality().equals(oldUser.getNationality())) {
					houseUser.setNationality(applyUser.getNationality());
					isUpdate = true;
				}
				//护照
				if (StringUtils.isNotBlank(applyUser.getPassportImgUri()) && !applyUser.getPassportImgUri().equals(oldUser.getPassportImgUri())) {
					houseUser.setPassportImgUri(applyUser.getPassportImgUri());
					isUpdate = true;
				}
				//护照
				if (StringUtils.isNotBlank(applyUser.getEntryImgUri()) && !applyUser.getEntryImgUri().equals(oldUser.getEntryImgUri())) {
					houseUser.setEntryImgUri(applyUser.getEntryImgUri());
					isUpdate = true;
				}
				if (isUpdate) {
					//更新之前user信息
					result = this.houseUserClient.update(houseUser);
				}
			} else {
				//申请记录转User
				houseUser = this.applyUserToUser(applyUser);
				Date beginDate = new Date();
				Calendar cd = Calendar.getInstance();
				cd.setTime(beginDate);
				cd.add(Calendar.YEAR, 20);
				Date endDate = cd.getTime();
				houseUser.setFaceBeginDate(beginDate);
				houseUser.setFaceEndDate(endDate);
				//往user增加faceEnable并设置为0
//                    user.setFaceEnable(OperationConstant.ZERO);
				//新增一个user
				R<HouseUser> houseUserR = this.houseUserClient.applySave(houseUser);
				houseUser = houseUserR.getData();
				applyUser.setUserId(houseUser.getId());
				result = this.updateById(applyUser);
				//新增人数
				this.communityClient.addPersonNum(houseUser.getAgencyId(), houseUser.getResidentialId()
					, houseUser.getBuildingId(), houseUser.getUnitId(), houseUser.getFloorId(), houseUser.getRoomId());

			}

			//---------------------------------------------------------------------------
			//下发人脸
			if (oldUser != null) {
				if (houseUser.getFaceEnable() == 2) {
					// 人脸已禁用
				} else {
					houseUser.setFaceUrl(confClient.addPrefix(houseUser.getFaceUrl()));
					pushFace(houseUser, 1);//2代表更新人脸
				}
			} else {
				houseUser.setFaceUrl(confClient.addPrefix(houseUser.getFaceUrl()));
				pushFace(houseUser, 1);//1代表新下发人脸
			}

		}
		return result;
	}

	/**
	 * 添加家人
	 * @param applyUser
	 * @return
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public boolean addApplyUserForFamily(ApplyUser applyUser) {
		applyUser.setFaceUrl(confClient.removePrefix(applyUser.getFaceUrl()));
		applyUser.setEntryImgUri(confClient.removePrefix(applyUser.getEntryImgUri()));
		applyUser.setPassportImgUri(confClient.removePrefix(applyUser.getPassportImgUri()));
		boolean save = false;
		if(applyUser.getType() != 0){
			applyUser.setAuditStatus(CommonConstant.UserAuditStatus.pass.getValue());
			this.save(applyUser);
			//构造一个HouseUser
			HouseUser houseUser = this.applyUserToUser(applyUser);
			save = houseUserClient.save(houseUser);
			if(save){
				//新增人数
				communityClient.addPersonNum(houseUser.getAgencyId(), houseUser.getResidentialId()
					, houseUser.getBuildingId(), houseUser.getUnitId(), houseUser.getFloorId(), houseUser.getRoomId());
				//给成员和租户下发人脸
				UserAccessPermissionsDTO userAccessPermissionsDTO = new UserAccessPermissionsDTO();
				userAccessPermissionsDTO.setUserId(Func.toStr(houseUser.getId()));
				userAccessPermissionsDTO.setUserFace(houseUser.getFaceUrl());
				userAccessPermissionsDTO.setUserType(CommonConstant.UserFlag.HOUSE_USER_FLAG.getValue());
				userAccessPermissionsDTO.setTargetType(1);
				List<DoorDeviceVO> doorDeviceVOList = doorDeviceClient.getListByResidentialAndUnit(houseUser.getResidentialId(), houseUser.getUnitId(), 1);
				if (doorDeviceVOList.size() != 0) {
					List<Long> deviceIdList = doorDeviceVOList.stream().map(DoorDeviceVO::getId).collect(Collectors.toList());
					userAccessPermissionsDTO.setDeviceIds(StringUtil.join(deviceIdList, ","));
					userAccessPermissionsService.pushFace(userAccessPermissionsDTO);
				}
				return save;

			}else{
				return false;
			}
		}else{
			return this.save(applyUser);
		}
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public R appUpdateAuditStatus(ApplyUserDTO applyUserDTO) {
		ApplyUser applyUser = this.getById(applyUserDTO.getId());
		if (applyUser.getAuditStatus() == OperationConstant.ZERO) {
			//更新记录状态
			applyUserDTO.setFaceUrl(confClient.removePrefix(applyUserDTO.getFaceUrl()));
			applyUserDTO.setPassportImgUri(confClient.removePrefix(applyUserDTO.getPassportImgUri()));
			applyUserDTO.setEntryImgUri(confClient.removePrefix(applyUserDTO.getEntryImgUri()));
			applyUserDTO.setCheckDate(new Date());
			boolean applyUpdate = this.updateById(applyUserDTO);
			if(applyUpdate){
				Member member = new Member();
				member.setId(applyUser.getMemberId());
				if(applyUserDTO.getAuditStatus() == 1){ //通过
					//申请记录转User
					HouseUser houseUser = this.applyUserToUser(applyUser);
					R r = this.houseUserClient.applySave(houseUser);
					if(r.isSuccess()){
						member.setState(OperationConstant.TWO);
						this.memberClient.update(member);
						//下发默认开门权限
						UserAccessPermissionsDTO userAccessPermissionsDTO = new UserAccessPermissionsDTO();
						userAccessPermissionsDTO.setUserId(Func.toStr(houseUser.getId()));
						userAccessPermissionsDTO.setUserType(CommonConstant.UserFlag.HOUSE_USER_FLAG.getValue());
						userAccessPermissionsDTO.setTargetType(1);
						userAccessPermissionsDTO.setResidentialId(houseUser.getResidentialId());
						userAccessPermissionsDTO.setUnitId(houseUser.getUnitId());
						userAccessPermissionsDTO.setRoomId(houseUser.getRoomId());
						userAccessPermissionsDTO.setUserFace(confClient.addPrefix(applyUserDTO.getFaceUrl()));
						userAccessPermissionsDTO.setTenantId(houseUser.getTenantId());
						userAccessPermissionsService.authPushPermissions(userAccessPermissionsDTO);
					}else{
						return R.fail("住户新增失败");
					}
					//新增小区入住人数
					this.communityClient.addPersonNum(houseUser.getAgencyId(), houseUser.getResidentialId(), houseUser.getBuildingId(), houseUser.getUnitId(), houseUser.getFloorId(), houseUser.getRoomId());
				}else if(applyUserDTO.getAuditStatus() == 2){ //不通过
					member.setState(OperationConstant.ZERO);
					this.memberClient.update(member);
				}
				return R.success("审核成功");
			}else{
				return R.fail("申请记录更新失败");
			}
		}else{
			return R.fail("已审核记录不能重复审核");
		}
	}

	@Override
	public R updateAuditStatus(ApplyUserDTO applyUserDTO) {
		ApplyUser applyUser = this.getById(applyUserDTO.getId());
		if (applyUser.getAuditStatus() == OperationConstant.ZERO) {
			//更新记录状态
			applyUserDTO.setFaceUrl(confClient.removePrefix(applyUserDTO.getFaceUrl()));
			applyUserDTO.setPassportImgUri(confClient.removePrefix(applyUserDTO.getPassportImgUri()));
			applyUserDTO.setEntryImgUri(confClient.removePrefix(applyUserDTO.getEntryImgUri()));
			applyUserDTO.setCheckDate(new Date());
			boolean applyUpdate = this.updateById(applyUserDTO);
			if(applyUpdate){
				Member member = new Member();
				member.setId(applyUser.getMemberId());
				if(applyUserDTO.getAuditStatus() == 1){ //通过
					//申请记录转User
					HouseUser houseUser = this.applyUserToUser(applyUser);
					R r = this.houseUserClient.applySave(houseUser);
					if(r.isSuccess()){
						member.setState(OperationConstant.TWO);
						this.memberClient.update(member);
						//下发默认开门权限
						UserAccessPermissionsDTO userAccessPermissionsDTO = new UserAccessPermissionsDTO();
						userAccessPermissionsDTO.setUserId(Func.toStr(houseUser.getId()));
						userAccessPermissionsDTO.setUserType(CommonConstant.UserFlag.HOUSE_USER_FLAG.getValue());
						userAccessPermissionsDTO.setTargetType(1);
						userAccessPermissionsDTO.setResidentialId(houseUser.getResidentialId());
						userAccessPermissionsDTO.setUnitId(houseUser.getUnitId());
						userAccessPermissionsDTO.setRoomId(houseUser.getRoomId());
						userAccessPermissionsDTO.setUserFace(confClient.addPrefix(applyUserDTO.getFaceUrl()));
						userAccessPermissionsDTO.setTenantId(houseUser.getTenantId());
						userAccessPermissionsService.authPushPermissions(userAccessPermissionsDTO);
					}else{
						return R.fail("住户新增失败");
					}
					//新增小区入住人数
					this.communityClient.addPersonNum(houseUser.getAgencyId(), houseUser.getResidentialId(), houseUser.getBuildingId(), houseUser.getUnitId(), houseUser.getFloorId(), houseUser.getRoomId());
				}else if(applyUserDTO.getAuditStatus() == 2){ //不通过
					member.setState(OperationConstant.ZERO);
					this.memberClient.update(member);
				}
				return R.success("审核成功");
			}else{
				return R.fail("申请记录更新失败");
			}
		}else{
			return R.fail("已审核记录不能重复审核");
		}
	}

	private HouseUser applyUserToUser(ApplyUser applyUser) {
		HouseUser user = new HouseUser();
		user.setName(applyUser.getName());
		user.setAuditStatus(CommonConstant.UserAuditStatus.pass.getValue());
		if (StringUtils.isNotBlank(applyUser.getFaceUrl())) {
			user.setFaceUrl(applyUser.getFaceUrl());
			user.setImageMd5(applyUser.getImageMd5());
			user.setFaceEnable(1); //未激活
		} else {
			user.setAuditStatus(-1); //未上传人脸
			user.setFaceEnable(-1); //未上传人脸
		}
		user.setSex(applyUser.getSex());
		user.setNationality(applyUser.getNationality());
		if (StringUtils.isNotBlank(applyUser.getPassportImgUri())) {
			user.setPassportImgUri(applyUser.getPassportImgUri());
		}
		if (StringUtils.isNotBlank(applyUser.getEntryImgUri())) {
			user.setEntryImgUri(applyUser.getEntryImgUri());
		}
		user.setType(applyUser.getType());
		user.setIdCard(applyUser.getIdCard());
		user.setPhone(applyUser.getPhone());
		user.setBuildingName(applyUser.getBuildingName());
		user.setBuildingId(applyUser.getBuildingId());
		user.setRoomId(applyUser.getRoomId());
		user.setRoomName(applyUser.getRoomName());
		user.setUnitId(applyUser.getUnitId());
		user.setUnitName(applyUser.getUnitName());
		user.setResidentialId(applyUser.getResidentialId());
		user.setResidentialName(applyUser.getResidentialName());
		user.setCreateType(applyUser.getCreateType());
		return user;
	}

	/**
	 *
	 * @param user
	 * @param operType 1：新增编辑人脸、2删除人脸
	 */
	private void pushFace(HouseUser user, Integer operType) {

		if (StringUtils.isNotBlank(user.getFaceUrl())) {
			Conf searchConf = new Conf();
			searchConf.setConfToken("file.server.host");
			Conf fileConf = this.confClient.detail(searchConf);
			List<Map<String, Object>> userFaceList = new ArrayList<>(1);
			Map<String, Object> map = new HashMap<>(3);
			map.put("imgMd5", user.getImageMd5());
			String faceUrl = fileConf != null ? fileConf.getConfValue() + user.getFaceUrl() : "" + user.getFaceUrl();
			map.put("imgSrc", faceUrl);
			userFaceList.add(map);
			//  下发人脸-到通用设备
			UserInfoDto dto = new UserInfoDto();
			dto.setId(CommonConstant.UserFlag.HOUSE_USER_FLAG.getValue() + user.getId());
			dto.setFaceCodeList(userFaceList);
			dto.setFaceUrl(faceUrl);
			dto.setBeginDate(user.getFaceBeginDate());
			dto.setEndDate(user.getFaceEndDate());
			DispatchTask task = new DispatchTask();
			task.setUnitId(user.getUnitId());
			task.setXqId(user.getResidentialId());
			task.setData(dto);
			this.doorDeviceClient.pushUserFace(task, operType);
		}
	}

}
