/*
 *      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.springblade.common.constant.CommonConstant;
import org.springblade.community.entity.Agency;
import org.springblade.community.entity.Residential;
import org.springblade.community.feign.IAgencyClient;
import org.springblade.community.feign.IResidentialClient;
import org.springblade.core.secure.BladeUser;
import org.springblade.core.secure.utils.AuthUtil;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.constant.BladeConstant;
import org.springblade.core.tool.utils.DateUtil;
import org.springblade.core.tool.utils.StringUtil;
import org.springblade.device.entity.DoorDevice;
import org.springblade.device.feign.IDoorDeviceClient;
import org.springblade.enterprise.entity.Enterprise;
import org.springblade.enterprise.entity.Staff;
import org.springblade.enterprise.feign.IEnterpriseClient;
import org.springblade.enterprise.feign.IStaffClient;
import org.springblade.estate.dto.AccessRecordDTO;
import org.springblade.estate.entity.AccessRecord;
import org.springblade.estate.entity.AccessStatistics;
import org.springblade.estate.entity.GuestRecord;
import org.springblade.estate.feign.IGuestRecordClient;
import org.springblade.estate.service.IAccessStatisticsService;
import org.springblade.estate.vo.AccessRecordVO;
import org.springblade.estate.mapper.AccessRecordMapper;
import org.springblade.estate.service.IAccessRecordService;
import org.springblade.core.mp.base.BaseServiceImpl;
import org.springblade.person.entity.HouseUser;
import org.springblade.person.feign.IHouseUserClient;
import org.springblade.person.vo.HouseUserVO;
import org.springblade.system.user.entity.User;
import org.springblade.system.user.feign.IUserClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import org.springframework.util.Assert;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 *  服务实现类
 *
 * @author BladeX
 * @since 2021-03-30
 */
@Service
public class AccessRecordServiceImpl extends BaseServiceImpl<AccessRecordMapper, AccessRecord> implements IAccessRecordService {

	@Autowired
	private IAgencyClient agencyClient;
	@Autowired
	private IResidentialClient residentialClient;
	@Autowired
	private IEnterpriseClient enterpriseClient;
	@Autowired
	private IStaffClient staffClient;
	@Autowired
	private IDoorDeviceClient doorDeviceClient;
	@Autowired
	private IGuestRecordClient guestRecordClient;
	@Autowired
	private IUserClient userClient;
	@Autowired
	private IAccessStatisticsService accessStatisticsService;
	@Autowired
	private IHouseUserClient houseUserClient;

	@Override
	public IPage<AccessRecordVO> selectAccessRecordPage(IPage<AccessRecordVO> page, AccessRecordVO accessRecord) {
		return page.setRecords(baseMapper.selectAccessRecordPage(page, accessRecord));
	}

	@Override
	public Integer selectDayAccessRecordCount() {
		return baseMapper.selectDayAccessRecordCount();
	}

	@Override
	public Integer selectWeekAccessRecordCount() {
		return baseMapper.selectWeekAccessRecordCount();
	}

	@Override
	public Integer selectMonthAccessRecordCount() {
		return baseMapper.selectMonthAccessRecordCount();
	}

	@Override
	public Integer selectYearAccessRecordCount() {
		return baseMapper.selectYearAccessRecordCount();
	}

	@Override
	public R generateAccessRecord(AccessRecordDTO accessRecord) {
		DoorDevice doorDevice = doorDeviceClient.getBySerialNum(accessRecord.getSerialNum());
		Agency agency = agencyClient.getById(doorDevice.getAgencyId());
		Residential residential = residentialClient.getById(doorDevice.getResidentialId());
		String userId = accessRecord.getUserId();
		if(CommonConstant.UserFlag.ENTERPRISE_STAFF_FLAG.getValue().equals(accessRecord.getUserType())){
			Staff staff = staffClient.getById(Long.parseLong(userId));
			Enterprise enterprise = enterpriseClient.getById(staff.getEnterpriseId());
			accessRecord.setEnterpriseId(staff.getEnterpriseId());
			accessRecord.setEnterpriseName(enterprise.getEnterpriseName());
		}else if(CommonConstant.UserFlag.GUEST_FLAG.getValue().equals(accessRecord.getUserType())){
			GuestRecord guestRecord = guestRecordClient.getById(Long.parseLong(userId));
			Enterprise enterprise = enterpriseClient.getById(guestRecord.getEnterpriseId());
			if(enterprise != null){
				accessRecord.setEnterpriseId(guestRecord.getEnterpriseId());
				accessRecord.setEnterpriseName(enterprise.getEnterpriseName());
			}
		}
		accessRecord.setAgencyId(agency.getId());
		accessRecord.setResidentialId(residential.getId());
		accessRecord.setAgencyName(agency.getName());
		accessRecord.setResidentialName(residential.getName());
		accessRecord.setTenantId(doorDevice.getTenantId());
		Date today = new Date();
		accessRecord.setCreateTime(today);
		accessRecord.setUpdateTime(today);
		accessRecord.setIsDeleted(BladeConstant.DB_NOT_DELETED);
		accessRecord.setDeviceId(doorDevice.getId());
		accessRecord.setDeviceName(doorDevice.getName());
		accessRecord.setDeviceAddress(doorDevice.getAddress());
		accessRecord.setIsOut(doorDevice.getIsOut());
		int insert = this.baseMapper.insert(accessRecord);
		if(insert > 0){
			SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
			String date = sdf.format(accessRecord.getCreateTime());
			AccessStatistics accessStatistics = accessStatisticsService.getByDate(date, accessRecord.getTenantId());
			if(accessStatistics != null){
				if(CommonConstant.UserFlag.ENTERPRISE_STAFF_FLAG.getValue().equals(accessRecord.getUserType())){
					accessStatistics.setStaffCnt(accessStatistics.getStaffCnt() + 1);
				}else if(CommonConstant.UserFlag.GUEST_FLAG.getValue().equals(accessRecord.getUserType())){
					accessStatistics.setGuestCnt(accessStatistics.getGuestCnt() + 1);
				}else if(CommonConstant.UserFlag.HOUSE_USER_FLAG.getValue().equals(accessRecord.getUserType())){
					accessStatistics.setHouseUserCnt(accessStatistics.getHouseUserCnt() + 1);
				}
			}else{
				accessStatistics = new AccessStatistics();
				accessStatistics.setDate(DateUtil.parse(date, "yyyy-MM-dd"));
				accessStatistics.setTenantId(accessRecord.getTenantId());
				if(CommonConstant.UserFlag.ENTERPRISE_STAFF_FLAG.getValue().equals(accessRecord.getUserType())){
					accessStatistics.setStaffCnt(1);
				}else if(CommonConstant.UserFlag.GUEST_FLAG.getValue().equals(accessRecord.getUserType())){
					accessStatistics.setGuestCnt(1);
				}else if(CommonConstant.UserFlag.HOUSE_USER_FLAG.getValue().equals(accessRecord.getUserType())){
					accessStatistics.setHouseUserCnt(1);
				}
			}
			accessStatisticsService.statCount(accessStatistics);
			return R.status(true);
		}
		return R.status(false);
	}

	@Override
	public R generateAccessRecord(String serialNum, Long userId, String userFace, Integer userType, Integer openType,
								  Integer openSuccess, String failReason, String commandSeq, String temperature, Date openDate) {
		Agency agency = null;
		Residential residential = null;
		Enterprise enterprise = null;
		Long enterpriseId = null;
		String enterpriseName = null;
		String userName = null;
		DoorDevice doorDevice = doorDeviceClient.getBySerialNum(serialNum);
		if(userType.intValue() == CommonConstant.UserType.STAFF.getType().intValue()){
			Staff staff = staffClient.getById(userId);
			Assert.notNull(staff, "企业员工不存在");
			agency = agencyClient.getById(staff.getAgencyId());
			residential = residentialClient.getById(staff.getResidentialId());
			enterprise = enterpriseClient.getById(staff.getEnterpriseId());
			enterpriseId = enterprise.getId();
			enterpriseName = enterprise.getEnterpriseName();
			userName = staff.getRealName();
		}else if(userType.intValue() == CommonConstant.UserType.GUEST.getType().intValue()){
			GuestRecord guest = guestRecordClient.getById(userId);
			Assert.notNull(guest, "访客记录不存在");
			agency = agencyClient.getById(guest.getAgencyId());
			residential = residentialClient.getById(guest.getResidentialId());
			enterprise = enterpriseClient.getById(guest.getEnterpriseId());
			enterpriseId = enterprise.getId();
			enterpriseName = enterprise.getEnterpriseName();
			userName = guest.getGuestName();
		}else if(userType.intValue() == CommonConstant.UserType.ADMIN.getType().intValue()){
			agency = agencyClient.getById(doorDevice.getAgencyId());
			residential = residentialClient.getById(doorDevice.getResidentialId());
			BladeUser user = AuthUtil.getUser();
			if(user != null){
				userName = user.getUserName();
			}
		}
		AccessRecord record = new AccessRecord();
		record.setAgencyId(agency.getId());
		record.setAgencyName(agency.getName());
		record.setResidentialId(residential.getId());
		record.setResidentialName(residential.getName());
		record.setEnterpriseId(enterpriseId);
		record.setEnterpriseName(enterpriseName);
		record.setUserName(userName);
		record.setTenantId(residential.getTenantId());
		record.setFaceUrl(userFace);
		record.setOpenType(openType);
		record.setOpenSuccess(openSuccess);
		record.setFailReason(failReason);
		record.setDeviceAddress(doorDevice.getAddress());
		record.setSerialNum(doorDevice.getSerialNum());
		record.setDeviceId(doorDevice.getId());
		record.setCommandSeq(commandSeq);
		record.setTemperature(StringUtil.isNoneBlank(temperature) ? new BigDecimal(temperature).compareTo(BigDecimal.ZERO) == 1 ? temperature : null : null);
		record.setOpenTime(openDate);
		record.setIsOut(doorDevice.getIsOut());
		return R.status(this.save(record));
	}

}
