/*
 *      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.guest.controller;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import javassist.compiler.ast.CondExpr;
import lombok.AllArgsConstructor;

import javax.validation.Valid;

import lombok.extern.slf4j.Slf4j;
import org.springblade.common.Constants;
import org.springblade.community.agency.entity.Agency;
import org.springblade.community.agency.service.IAgencyService;
import org.springblade.community.enterprise.entity.Enterprise;
import org.springblade.community.enterprise.service.IEnterpriseService;
import org.springblade.community.repeater.entity.Repeater;
import org.springblade.community.repeater.service.IRepeaterService;
import org.springblade.community.residential.entity.Residential;
import org.springblade.community.residential.service.IResidentialService;
import org.springblade.community.staff.entity.UserInfoDto;
import org.springblade.core.log.logger.BladeLogger;
import org.springblade.core.mp.support.Condition;
import org.springblade.core.mp.support.Query;
import org.springblade.core.secure.BladeUser;
import org.springblade.core.tenant.mp.TenantEntity;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.Func;
import org.springblade.core.tool.utils.StringUtil;
import org.springblade.modules.system.entity.User;
import org.springblade.mq.enums.Instruct;
import org.springblade.mq.service.MsgPublishService;
import org.springblade.openinterface.facedevice.qinlin.beans.QinLinApiResultBean;
import org.springblade.openinterface.facedevice.qinlin.util.QinLinHttpUtil;
import org.springblade.openinterface.facedevice.qinlin.vo.QLinUser;
import org.springblade.smartapplication.facedevice.entity.FaceDevice;
import org.springblade.smartapplication.facedevice.service.IFaceDeviceService;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.RequestParam;
import com.baomidou.mybatisplus.core.metadata.IPage;
import org.springblade.estate.guest.entity.Guest;
import org.springblade.estate.guest.vo.GuestVO;
import org.springblade.estate.guest.wrapper.GuestWrapper;
import org.springblade.estate.guest.service.IGuestService;
import org.springblade.core.boot.ctrl.BladeController;

import java.sql.Time;
import java.sql.Timestamp;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 控制器
 *
 * @author BladeX
 * @since 2021-03-10
 */
@RestController
@AllArgsConstructor
@RequestMapping("estate/guest")
@Api(value = "访客授权", tags = "访客授权")
@Slf4j
public class GuestController extends BladeController {

	private final IGuestService guestService;
	private final IEnterpriseService enterpriseService;
	private final IResidentialService residentialService;
	private final IAgencyService agencyService;
	private final IRepeaterService repeaterService;
	private final MsgPublishService msgPublishService;
	private final IFaceDeviceService faceDeviceService;
	private final QinLinHttpUtil qinLinHttpUtil;
	private final BladeLogger bladeLogger;
	private final RedisTemplate<String,String> redisTemplate;

	/**
	 * 详情
	 */
	@GetMapping("/detail")
	@ApiOperationSupport(order = 1)
	@ApiOperation(value = "详情", notes = "传入guest")
	public R<GuestVO> detail(Guest guest) {
		Guest detail = guestService.getOne(Condition.getQueryWrapper(guest));
		return R.data(GuestWrapper.build().entityVO(detail));
	}

	/**
	 * 分页
	 */
	@GetMapping("/list")
	@ApiOperationSupport(order = 2)
	@ApiOperation(value = "分页", notes = "传入guest")
	public R<IPage<GuestVO>> list(@RequestParam Map<String, Object> guest, Query query, BladeUser bladeUser) {
		QueryWrapper<Guest> queryWrapper = Condition.getQueryWrapper(guest, Guest.class);
		queryWrapper.lambda().orderByDesc(Guest::getCreateTime);
		IPage<Guest> pages = guestService.page(Condition.getPage(query), (Wrapper)(!bladeUser.getTenantId().equals("000000") ? (Wrapper)queryWrapper.lambda().eq(Guest::getTenantId, bladeUser.getTenantId()) : queryWrapper));
//		IPage<Guest> pages = guestService.page(Condition.getPage(query), Condition.getQueryWrapper(guest).lambda().eq(Guest::getTenantId,bladeUser.getTenantId()).orderByDesc(Guest::getCreateTime));
		return R.data(GuestWrapper.build().pageVO(pages));
	}


	/**
	 * 自定义分页
	 */
	@GetMapping("/page")
	@ApiOperationSupport(order = 3)
	@ApiOperation(value = "分页", notes = "传入guest")
	public R<IPage<GuestVO>> page(GuestVO guest, Query query) {
		IPage<GuestVO> pages = guestService.selectGuestPage(Condition.getPage(query), guest);
		return R.data(pages);
	}

	/**
	 * 新增
	 */
	@PostMapping("/save")
	@ApiOperationSupport(order = 4)
	@ApiOperation(value = "新增", notes = "传入guest")
	public R save(@Valid @RequestBody Guest guest) {
		return R.status(guestService.save(guest));
	}

	/**
	 * 修改
	 */
	@PostMapping("/update")
	@ApiOperationSupport(order = 5)
	@ApiOperation(value = "修改", notes = "传入guest")
	public R update(@Valid @RequestBody Guest guest) {
		return R.status(guestService.updateById(guest));
	}

	/**
	 * 新增或修改
	 */
	@PostMapping("/submit")
	@ApiOperationSupport(order = 6)
	@ApiOperation(value = "新增或修改", notes = "传入guest")
	public R submit(@Valid @RequestBody Guest guest) {
		boolean saveOrUpdate = guestService.saveOrUpdate(guest);
		if(saveOrUpdate){
			if (guest.getCheckState() == 1  && StringUtil.isNotBlank(guest.getImageUri())) {//若审核通过，下发访客信息到门禁设备，如果访客有人脸信息也下发到门禁设备
				Long agencyId = guest.getAgencyId();
				Long residentialId = guest.getResidentialId();
				Agency agency = this.agencyService.getById(agencyId);
				Residential residential = this.residentialService.getById(residentialId);
				String agencyPos = agency.getOrgPosition();
				String residentialPos = residential.getOrgPosition();
				List<FaceDevice> faceDeviceList = faceDeviceService.selectByAgencyOrXqOrUnitPositionList(agencyPos, residentialPos, null);
				if (faceDeviceList == null || faceDeviceList.size() <= 0) {
					log.error("园区访客信息下发到设备时找不到设备","访客信息"+ guest.toString());
					return R.fail("审核通过但是找不到设备下发访客信息");
				}
				List<FaceDevice> jvtDeviceList = new ArrayList<>();
				List<FaceDevice> qinLinDeviceList = new ArrayList<>();
				for (int i = 0; i < faceDeviceList.size(); i++) {
					FaceDevice faceDevice = faceDeviceList.get(i);
					if (faceDevice.getDeviceFactory() != null && faceDevice.getDeviceFactory().equals("JVT")) {
						jvtDeviceList.add(faceDevice);
					} else {
						qinLinDeviceList.add(faceDevice);
					}
				}
				//下发到亲邻设备
				String deviceIds = qinLinDeviceList.stream().map(FaceDevice::getMacAddress).collect(Collectors.joining(","));
				if (StringUtil.isNotBlank(deviceIds)) {
					QLinUser qLinUser = new QLinUser();
					qLinUser.setUserId(guest.getId().toString());//园区访客在门禁设备中的id为”999“加上访客的手机号码
					if (StringUtil.isNotBlank(guest.getImageUri())) {
						qLinUser.setFaceUrl(guest.getImageUri());
					}
					qLinUser.setDeviceIds(deviceIds);
					QinLinApiResultBean qinLinApiResultBean = qinLinHttpUtil.addUser(qLinUser);
					if (qinLinApiResultBean.getCode().equals(0)) {
						//存入缓存，值为「设备厂家」：『访客手机号』      有效期至预约日期当天最后一刻
						SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
						SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd");
						//访客授权人脸在预约日当天有效
						String interviewTime = guest.getInterviewTime();
						String endTime = interviewTime + " 23:59:59";

						Date endDate = null;
						try {
							endDate = sdf.parse(endTime);
						} catch (ParseException e) {
							e.printStackTrace();
						}
						redisTemplate.opsForValue().set(Constants.REDIS_GUEST_EFFECTIVE_TIME_QINLIN+guest.getGuestTel(),guest.toString());
						redisTemplate.expireAt(Constants.REDIS_GUEST_EFFECTIVE_TIME_QINLIN+guest.getGuestTel(),endDate);
						return R.status(true);
					} else {
						return R.fail("人脸下发门禁失败");
					}
				}else{
					return R.status(true);
				}
			}else{
				return R.status(true);
			}
		}else{
			return R.status(saveOrUpdate);
		}
	}

	/**
	 * 删除
	 */
	@PostMapping("/remove")
	@ApiOperationSupport(order = 7)
	@ApiOperation(value = "逻辑删除", notes = "传入ids")
	public R remove(@ApiParam(value = "主键集合", required = true) @RequestParam String ids) {
		return R.status(guestService.deleteLogic(Func.toLongList(ids)));
	}

	/**
	 * 申请
	 */
	@PostMapping("/application")
	@ApiOperationSupport(order = 8)
	@ApiOperation(value = "申请", notes = "guest")
	public R application(@Valid @RequestBody Guest guest,BladeUser bladeUser) {
		//用企业id判断访问的是企业还是园区
		if (guest.getEnterpriseId() != null) {
			Enterprise enterprise = this.enterpriseService.getById(guest.getEnterpriseId());
			Assert.notNull(enterprise, "选择的企业不存在");
			guest.setEnterpriseName(enterprise.getEnterpriseName());
			//区域信息
			Residential residential = this.residentialService.getById(enterprise.getResidentialId());
			guest.setResidentialId(residential.getId());
			guest.setResidentialName(residential.getName());
			//园区信息
			Agency agency = this.agencyService.getById(enterprise.getAgencyId());
			guest.setAgencyId(agency.getId());
			guest.setAgencyName(agency.getAgencyName()	);
			guest.setOrgPosition(enterprise.getOrgPosition());
		} else {
			Agency agency = this.agencyService.getById(guest.getAgencyId());
			Assert.notNull(agency, "选择的园区不存在");
			guest.setAgencyName(agency.getAgencyName());
			guest.setOrgPosition(agency.getOrgPosition());
		}
		guest.setTenantId(bladeUser.getTenantId());
		return R.status(guestService.save(guest));
	}

	/**
	 * 审核
	 */
	@PostMapping("/check")
	@ApiOperationSupport(order = 9)
	@ApiOperation(value = "审核", notes = "传入guest")
	public R check(@Valid @RequestBody Guest guest) {
		Guest oldGuest = guestService.getById(guest.getId());
		oldGuest.setCheckState(guest.getCheckState());
		oldGuest.setOpinion(guest.getOpinion());
		boolean result = guestService.updateById(oldGuest);
		if (result && guest.getCheckState() == 1) {//若审核通过，下发访客信息到门禁设备，如果访客有人脸信息也下发到门禁设备
			Long agencyId = oldGuest.getAgencyId();
			Long residentialId = oldGuest.getResidentialId();
			Agency agency = this.agencyService.getById(agencyId);
			Residential residential = this.residentialService.getById(residentialId);
			String agencyPos = agency.getOrgPosition();
			String residentialPos = residential.getOrgPosition();
			List<FaceDevice> faceDeviceList = faceDeviceService.selectByAgencyOrXqOrUnitPositionList(agencyPos, residentialPos, null);
			if (faceDeviceList == null || faceDeviceList.size() <= 0) {
				bladeLogger.error("园区访客信息下发到设备时找不到设备","访客信息"+oldGuest.toString());
				return R.fail("审核通过但是找不到设备下发访客信息");
			}
			List<FaceDevice> jvtDeviceList = new ArrayList<>();
			List<FaceDevice> qinLinDeviceList = new ArrayList<>();
			for (int i = 0; i < faceDeviceList.size(); i++) {
				FaceDevice faceDevice = faceDeviceList.get(i);
				if (faceDevice.getDeviceFactory() != null && faceDevice.getDeviceFactory().equals("JVT")) {
					jvtDeviceList.add(faceDevice);
				} else {
					qinLinDeviceList.add(faceDevice);
				}
			}
			//下发到巨龙设备
			if (jvtDeviceList.size() > 0) {
				List<Map<String, Object>> userFaceList = new ArrayList<>(1);
				Map<String, Object> map = new HashMap<>(3);
				map.put("imgMd5", "hghgfhgdgfdhgfjiuyy");
				map.put("imgSrc", oldGuest.getImageUri());
				userFaceList.add(map);
				//  下发人脸
				UserInfoDto dto = new UserInfoDto();
				dto.setId(Constants.GUEST_PRE+oldGuest.getGuestTel());
				dto.setName(oldGuest.getGuestName());
				dto.setFaceCodeList(userFaceList);
				SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
				SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd");
				//访客授权人脸在预约日当天有效
				String interviewTime = oldGuest.getInterviewTime();
				String beginTime = interviewTime + " 00:00:00";
				String endTime = interviewTime + " 23:59:59";
				try {
					Date beginDate =sdf.parse(beginTime);
					Date endDate = sdf.parse(endTime);
					dto.setBeginDate(beginDate);
					dto.setEndDate(endDate);
					jvtDeviceList.forEach(faceDevice -> {
						msgPublishService.publishJVT(dto, faceDevice.getMacAddress(), Instruct.JVT_ADD_USER);
						//存入缓存，值为「设备厂家」：『访客手机号』      有效期至预约日期当天最后一刻
						redisTemplate.opsForValue().set(Constants.REDIS_GUEST_EFFECTIVE_TIME_JVT+oldGuest.getGuestTel()+":"+faceDevice.getMacAddress(),oldGuest.toString());
						redisTemplate.expireAt(Constants.REDIS_GUEST_EFFECTIVE_TIME_JVT+oldGuest.getGuestTel(),endDate);
					});
				} catch (ParseException e) {
					e.printStackTrace();
				}

			}
			//下发到亲邻设备
			String deviceIds = qinLinDeviceList.stream().map(FaceDevice::getMacAddress).collect(Collectors.joining(","));
			if (StringUtil.isNotBlank(deviceIds)) {
				QLinUser qLinUser = new QLinUser();
				qLinUser.setUserId(Constants.GUEST_PRE+oldGuest.getGuestTel());//园区访客在门禁设备中的id为”999“加上访客的手机号码
				if (StringUtil.isNotBlank(oldGuest.getImageUri())) {
					qLinUser.setFaceUrl(oldGuest.getImageUri());
				}
				qLinUser.setDeviceIds(deviceIds);
				QinLinApiResultBean qinLinApiResultBean = qinLinHttpUtil.addUser(qLinUser);
				if (qinLinApiResultBean.getCode().equals(0)) {
					//存入缓存，值为「设备厂家」：『访客手机号』      有效期至预约日期当天最后一刻
					SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
					SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd");
					//访客授权人脸在预约日当天有效
					String interviewTime = oldGuest.getInterviewTime();
					String endTime = interviewTime + " 23:59:59";

					Date endDate = null;
					try {
						endDate = sdf.parse(endTime);
					} catch (ParseException e) {
						e.printStackTrace();
					}
					redisTemplate.opsForValue().set(Constants.REDIS_GUEST_EFFECTIVE_TIME_QINLIN+oldGuest.getGuestTel(),oldGuest.toString());
					redisTemplate.expireAt(Constants.REDIS_GUEST_EFFECTIVE_TIME_QINLIN+oldGuest.getGuestTel(),endDate);
					return R.status(true);
				} else {
					return R.fail("人脸下发门禁失败");
				}
			}

		}

		return R.status(result);
	}


	/**
	 * 园区小程序访客获取自己的申请记录，无需鉴权
	 */
	@GetMapping("/getByGuestOpenId")
	@ApiOperationSupport(order = 6)
	@ApiOperation(value = "新增或修改", notes = "传入guest")
	public R<IPage<GuestVO>> submit(Guest guest,Query query) {
		IPage<Guest> pages = guestService.page(Condition.getPage(query), Condition.getQueryWrapper(guest).lambda().orderByDesc(Guest::getCreateTime));
		return R.data(GuestWrapper.build().pageVO(pages));
	}


}
