/*
 *      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 cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.lang.Assert;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.springblade.common.constant.CommonConstant;
import org.springblade.core.mp.support.Condition;
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.entity.DoorDevice;
import org.springblade.device.feign.IDoorDeviceClient;
import org.springblade.device.vo.DoorDeviceVO;
import org.springblade.enterprise.entity.Staff;
import org.springblade.estate.dto.AuthorizeRecordsDTO;
import org.springblade.estate.dto.UserAccessPermissionsDTO;
import org.springblade.estate.entity.AuthorizeRecords;
import org.springblade.estate.entity.UserAccessPermissions;
import org.springblade.estate.vo.UserAccessPermissionsVO;
import org.springblade.estate.mapper.UserAccessPermissionsMapper;
import org.springblade.estate.service.IUserAccessPermissionsService;
import org.springblade.core.mp.base.BaseServiceImpl;
import org.springblade.estate.wrapper.UserAccessPermissionsWrapper;
import org.springblade.system.entity.DictBiz;
import org.springblade.system.expand.feign.IConfClient;
import org.springblade.system.feign.IDictBizClient;
import org.springblade.third.doordevice.dto.UserDeviceDTO;
import org.springblade.third.doordevice.feign.IDoorDeviceButtClient;
import org.springblade.third.dto.DeviceDTO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import org.springframework.util.StringUtils;

import java.text.SimpleDateFormat;
import java.util.List;
import java.util.stream.Collectors;

/**
 *  服务实现类
 *
 * @author BladeX
 * @since 2022-01-07
 */
@Service
public class UserAccessPermissionsServiceImpl extends BaseServiceImpl<UserAccessPermissionsMapper, UserAccessPermissions> implements IUserAccessPermissionsService {

	@Autowired
	private IDoorDeviceClient doorDeviceClient;
	@Autowired
	private IDoorDeviceButtClient doorDeviceButtClient;
	@Autowired
	private IConfClient confClient;
	@Autowired
	private IDictBizClient dictBizClient;

	@Override
	public IPage<UserAccessPermissionsVO> selectUserAccessPermissionsPage(IPage<UserAccessPermissionsVO> page, UserAccessPermissionsVO userAccessPermissions) {
		return page.setRecords(baseMapper.selectUserAccessPermissionsPage(page, userAccessPermissions));
	}

	@Override
	public R generateUserAccessPermissions(AuthorizeRecordsDTO authorizeRecordsDTO) {
		UserAccessPermissions permissions = null;
		List<UserAccessPermissions> permissionsList = this.getByCondition(authorizeRecordsDTO.getDeviceSerialNum(), authorizeRecordsDTO.getUserId());
		if(permissionsList.size() > 0){
			permissions = permissionsList.get(0);
		}else{
			permissions = new UserAccessPermissions();
		}
		DoorDevice doorDevice = doorDeviceClient.getBySerialNum(authorizeRecordsDTO.getDeviceSerialNum());
		permissions.setAgencyId(authorizeRecordsDTO.getAgencyId());
		permissions.setResidentialId(authorizeRecordsDTO.getResidentialId());
		permissions.setBuildingId(authorizeRecordsDTO.getBuildingId());
		permissions.setUnitId(authorizeRecordsDTO.getUnitId());
		permissions.setRoomId(authorizeRecordsDTO.getRoomId());
		permissions.setEnterpriseId(authorizeRecordsDTO.getEnterpriseId());
		permissions.setUserId(authorizeRecordsDTO.getUserId());
		permissions.setUserName(authorizeRecordsDTO.getUserName());
		permissions.setUserFace(authorizeRecordsDTO.getUserFace());
		permissions.setUserType(authorizeRecordsDTO.getUserType());
		permissions.setUserFace(authorizeRecordsDTO.getUserFace());
		permissions.setDeviceSerialNum(authorizeRecordsDTO.getDeviceSerialNum());
		permissions.setDeviceName(authorizeRecordsDTO.getDeviceName());
		permissions.setDeviceAddress(authorizeRecordsDTO.getDeviceAddress());
		permissions.setTenantId(authorizeRecordsDTO.getTenantId());
		permissions.setDeviceFactory(doorDevice.getDeviceFactory());
		permissions.setPermissions(authorizeRecordsDTO.getPermissions());
		String authReqData = authorizeRecordsDTO.getAuthReqData();
		JSONObject reqData = JSONObject.parseObject(authReqData);
		permissions.setUserFace(confClient.removePrefix(reqData.getString("userFaceUrl")));
		return R.status(saveOrUpdate(permissions));
	}

	@Override
	public R deleteUserAccessPermissions(AuthorizeRecordsDTO authorizeRecordsDTO) {
		return R.status(baseMapper.deleteUserAccessPermissions(authorizeRecordsDTO) > 0);
	}

	@Override
	public List<UserAccessPermissions> getByCondition(String serialNum, String userId) {
		LambdaQueryWrapper<UserAccessPermissions> lambdaQueryWrapper = new LambdaQueryWrapper<>();
		lambdaQueryWrapper.eq(UserAccessPermissions::getDeviceSerialNum, serialNum);
		lambdaQueryWrapper.eq(UserAccessPermissions::getUserId, userId);
		lambdaQueryWrapper.orderByDesc(UserAccessPermissions::getCreateTime);
		return this.list(lambdaQueryWrapper);
	}

	@Override
	public List<Long> getUserIdsByUserType(String userType) {
		QueryWrapper<UserAccessPermissions> queryWrapper = Condition.getQueryWrapper(new UserAccessPermissions());
		queryWrapper.select("DISTINCT(user_id)").lambda()
			.eq(UserAccessPermissions::getUserType, userType)
			.select(UserAccessPermissions::getUserId);
		List<Long> list = this.list(queryWrapper).stream().map(UserAccessPermissions::getUserId).mapToLong(Convert::toLong).boxed().collect(Collectors.toList());
		if (CollUtil.isEmpty(list)) {
			list.add(Long.valueOf("-1"));
		}
		return list;
	}

	@Override
	public R pushFace(UserAccessPermissionsDTO userAccessPermissionsDTO) {
		//这里的userId是拼接了用户类型的，比如QYYG_13349456569094，表示企业员工
		List<DoorDevice> deviceList = doorDeviceClient.listByIds(userAccessPermissionsDTO.getDeviceIds());
		if(deviceList != null && deviceList.size() > 0) {
			for (DoorDevice doorDevice : deviceList) {
				String serialNum = doorDevice.getSerialNum();
				String deviceFactory = doorDevice.getDeviceFactory();
				List<UserAccessPermissions> permissionsList = this.getByCondition(serialNum, userAccessPermissionsDTO.getUserId());
				UserDeviceDTO userDeviceDTO = new UserDeviceDTO();
				userDeviceDTO.setSerialNum(serialNum);
				userDeviceDTO.setTargetType(userAccessPermissionsDTO.getTargetType());
				userDeviceDTO.setUserId(userAccessPermissionsDTO.getUserId());
				userDeviceDTO.setUserType(userAccessPermissionsDTO.getUserType());
				userDeviceDTO.setUserFaceUrl(userAccessPermissionsDTO.getUserFace());
				userDeviceDTO.setUserName(userAccessPermissionsDTO.getUserName());
				userDeviceDTO.setDeviceFactory(deviceFactory);
//				userDeviceDTO.setTenantId(userAccessPermissionsDTO.getTenantId());
				if (userAccessPermissionsDTO.getEndTime() != null && userAccessPermissionsDTO.getBeginTime() != null) {
					SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
					userDeviceDTO.setStartTime(sdf.format(userAccessPermissionsDTO.getBeginTime()));
					userDeviceDTO.setEndTime(sdf.format(userAccessPermissionsDTO.getEndTime()));
				}
				if (permissionsList.size() > 0) {
					userDeviceDTO.setAddOrUpdate(2); //更新
				} else {
					userDeviceDTO.setAddOrUpdate(1); //新增
				}
				doorDeviceButtClient.pushFace(userDeviceDTO);
			}
			return R.success("下发成功");
		}else{
			return R.fail("请先添加设备");
		}
	}

	@Override
	public R autoPushFace(UserAccessPermissionsDTO userAccessPermissionsDTO) {
		List<DoorDeviceVO> doorDeviceVOList = doorDeviceClient.getListByResidentialAndUnit(userAccessPermissionsDTO.getResidentialId(), userAccessPermissionsDTO.getUnitId(), 1);
		if (doorDeviceVOList.size() == 0) {
			return R.status(true);
		}
		List<Long> deviceIdList = doorDeviceVOList.stream().map(DoorDeviceVO::getId).collect(Collectors.toList());
		userAccessPermissionsDTO.setDeviceIds(StringUtil.join(deviceIdList, ","));
		return this.pushFace(userAccessPermissionsDTO);
	}

	@Override
	public R authPushPermissions(UserAccessPermissionsDTO userAccessPermissionsDTO) {
		R<List<DictBiz>> dictListR = dictBizClient.getList("default_user_access_permissions");
		List<DictBiz> dictList = dictListR.getData();
		for(DictBiz dict : dictList){
			if(dict.getDictKey().equals(CommonConstant.UserAccessPermissions.FACE_OPEN_DOOR.getValue())){
				if(StringUtil.isNotBlank(userAccessPermissionsDTO.getUserFace())){
					this.autoPushFace(userAccessPermissionsDTO);
				}
			}else{
				List<DoorDeviceVO> doorDeviceVOList = doorDeviceClient.getListByResidentialAndUnit(userAccessPermissionsDTO.getResidentialId(), userAccessPermissionsDTO.getUnitId(), 1);
				if (doorDeviceVOList.size() == 0) {
					return R.status(true);
				}else{
					for(DoorDeviceVO doorDeviceVO : doorDeviceVOList){
						userAccessPermissionsDTO.setDeviceName(doorDeviceVO.getName());
						userAccessPermissionsDTO.setDeviceSerialNum(doorDeviceVO.getSerialNum());
						userAccessPermissionsDTO.setDeviceAddress(doorDeviceVO.getAddress());
						userAccessPermissionsDTO.setAgencyId(doorDeviceVO.getAgencyId());
						userAccessPermissionsDTO.setPermissions(Integer.parseInt(dict.getDictValue()));
						this.save(userAccessPermissionsDTO);
					}
				}
			}
		}
		return R.status(true);
	}

	@Override
	public R deleteFace(String userId, String userType) {
		List<UserAccessPermissions> permissionsList = this.listByUser(userId, userType);
		for(UserAccessPermissions permissions : permissionsList){
			String deviceSerialNum = permissions.getDeviceSerialNum();
			UserDeviceDTO userDeviceDTO = new UserDeviceDTO();
			userDeviceDTO.setSerialNum(deviceSerialNum);
			userDeviceDTO.setUserId(userId);
			userDeviceDTO.setUserType(userType);
			userDeviceDTO.setDeviceFactory(permissions.getDeviceFactory());
			userDeviceDTO.setUserName(permissions.getUserName());
			doorDeviceButtClient.deleteFace(userDeviceDTO);
		}
		return R.status(true);
	}

	@Override
	public List<UserAccessPermissions> listByUser(String userId, String userType) {
		LambdaQueryWrapper<UserAccessPermissions> lambdaQueryWrapper = new LambdaQueryWrapper<>();
		lambdaQueryWrapper.eq(UserAccessPermissions::getUserId, userId);
		lambdaQueryWrapper.eq(StringUtil.isNotBlank(userType), UserAccessPermissions::getUserType, userType);
		lambdaQueryWrapper.orderByDesc(UserAccessPermissions::getCreateTime);
		return this.list(lambdaQueryWrapper);
	}

	@Override
	public List<UserAccessPermissionsVO> getListByUserAndAddress(String userId, String userType, Long residentialId, Long unitId, Integer permissions) {
		LambdaQueryWrapper<UserAccessPermissions> lambdaQueryWrapper = new LambdaQueryWrapper<>();
		lambdaQueryWrapper.eq(UserAccessPermissions::getUserId, userId);
		lambdaQueryWrapper.eq(StringUtil.isNotBlank(userType), UserAccessPermissions::getUserType, userType);
		lambdaQueryWrapper.eq(residentialId != null, UserAccessPermissions::getResidentialId, residentialId);
		lambdaQueryWrapper.eq(unitId != null, UserAccessPermissions::getUnitId, unitId);
		lambdaQueryWrapper.eq(permissions != null, UserAccessPermissions::getPermissions, permissions);
		lambdaQueryWrapper.orderByDesc(UserAccessPermissions::getCreateTime);
		return UserAccessPermissionsWrapper.build().listVO(this.list(lambdaQueryWrapper));
	}

}
