package com.sptg.gateway.controller;

import com.baomidou.mybatisplus.plugins.Page;
import com.sptg.common.core.beans.PageBean;
import com.sptg.common.core.beans.ResultBean;
import com.sptg.common.core.beans.ResultEnum;
import com.sptg.common.core.constant.OperationConstant;
import com.sptg.common.core.constant.UserFlagConstant;
import com.sptg.common.core.util.JsonUtils;
import com.sptg.device.api.constant.DeviceConstants;
import com.sptg.device.api.dto.DeviceDto;
import com.sptg.device.api.entity.Device;
import com.sptg.device.api.feigns.DeviceFeign;
import com.sptg.estate.api.dto.GuestAuthorizeDto;
import com.sptg.estate.api.dto.UserInfoDto;
import com.sptg.estate.api.entity.*;
import com.sptg.estate.api.feigns.*;
import com.sptg.estate.api.stream.SyncNoticeDataDeviceProduceInterface;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.integration.support.MessageBuilder;
import org.springframework.messaging.Message;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import java.util.Date;

/**
 * title: EstateController
 * package: com.sptg.gateway.controller
 * description: 物业控制器
 *
 *
 *
 */
@Slf4j
@RestController
@RequiredArgsConstructor
public class EstateController {

    private final AccessCardFeign accessCardFeign;
    private final BaseUserFeign baseUserFeign;
    private final AccessRecordsFeign accessRecordsFeign;
    private final DeviceFeign deviceFeign;
    private final NoticePushDetailsFeign noticePushDetailsFeign;
    private final GuestAuthorizeFeign guestAuthorizeFeign;
    private final VideoCallAccountFeign videoCallAccountFeign;
    private final UnitFeign unitFeign;
    private final SyncNoticeDataDeviceProduceInterface syncNoticeDataDeviceProduceInterface;

    /**
     * 同步设备公告数据
     * @param device 设备信息
     * @return ResultBean
     */
    @PostMapping(value = "/notice/sync/device/data")
    public ResultBean syncData(@RequestBody DeviceDto device){
        Assert.hasText(device.getSerialNumber(),"设备序列号不能为空");
        //  通知队列下发
        Message<String> build = MessageBuilder.withPayload(device.getSerialNumber()).build();
        this.syncNoticeDataDeviceProduceInterface.output().send(build);
        return new ResultBean<>(ResultEnum.SUCCESS);
    }

    /**
     * 功能描述: 公告下发任务执行完毕
     * @param dto
     * {
     *     taskId       :   任务Id
     *     serialNumber :   设备序列号
     *     pushStatus   :   任务执行状态{ 1：成功，2：失败 }
     *     remark       :   备注（失败原因）,选填
     * }
     * @return ResultBean<Boolean>
     *
     *
     */
    @PostMapping(value = "/notice/task/end")
    public ResultBean<Boolean> taskEnd(@RequestBody NoticePushDeviceDetails dto){
        Assert.notNull(dto.getTaskId(),"任务Id不能为空");
        Assert.hasText(dto.getSerialNumber(),"设备序列号不能为空");
        Assert.notNull(dto.getPushStatus(),"任务执行状态不能为空");
        return this.noticePushDetailsFeign.updatePushStatus(dto);
    }

    /**
     * 功能描述: 开门记录
     * @param records
     * {
     *      serialNumber:   设备序列号,必填
     *      userId      :   用户Id,必填
     *      snapshoUri  :   抓拍图片的路径
     *      openDoorType:   0- 人脸 1-密码 2-刷卡 3-远程
     *      accessCardNo:   开门使用的卡号
     *      createDate  :   开门时间,必填
     * }
     * @return ResultBean<Boolean>
     *
     *
     */
    @PostMapping(value = "/estate/open/door/log")
    public ResultBean<Boolean> playLog(@RequestBody AccessRecords records){
        log.warn("----开门记录----");
        log.warn(JsonUtils.objectToJson(records));
        //  字段校验
        Assert.hasText(records.getSerialNumber(),"设备序列号不能为空");
        Assert.notNull(records.getOpenDoorType(),"开门方式不能为空");
        Assert.notNull(records.getAccessDate(),"出入时间不能为空");
        //  获取设备信息
        Device device = this.deviceFeign.getEntityBySerialNumber(records.getSerialNumber());
        Assert.notNull(device,"设备序列号不存在");
        //  设备信息
        records.setDeviceId(device.getId());
        records.setDeviceName(device.getName());
        records.setSerialNumber(device.getSerialNumber());
        records.setInstallPath(device.getInstallPath());
        records.setIsOut(device.getIsOut());
        //  小区信息
        records.setResidentialId(device.getXqId());
        records.setResidentialName(device.getXqName());
//        records.setUnitId(device.getUnitId());
//        records.setUnitName(device.getDyName());
        //  机构信息
        records.setOrgPosition(device.getOrgPosition());
        records.setEstatePosition(device.getEstatePosition());
        records.setRootOrgId(device.getRootOrgId());
        //  保存出入记录
        return this.accessRecordsFeign.addAccessRecords(records);
    }

    /**
     * 功能描述: 大豪设备开门记录
     * @param records
     * {
     *      serialNumber:   设备序列号,必填
     *      userId      :   用户Id,必填
     *      snapshoUri  :   抓拍图片的路径
     *      openDoorType:   0- 人脸 1-密码 2-刷卡 3-远程
     *      accessCardNo:   开门使用的卡号
     *      createDate  :   开门时间,必填
     * }
     * @return ResultBean<Boolean>
     *
     *
     */
    @PostMapping(value = "/dh/estate/open/door/log")
    public ResultBean<Boolean> dhPlayLog(@RequestBody AccessRecords records){
        //  字段校验
        Assert.hasText(records.getSerialNumber(),"设备序列号不能为空");
        Assert.notNull(records.getOpenDoorType(),"开门方式不能为空");
//        Assert.notNull(records.getAccessDate(),"出入时间不能为空");
        this.log.warn(JsonUtils.objectToJson(records));
        //  获取设备信息
        Device device = this.deviceFeign.getEntityBySerialNumber(records.getSerialNumber());
        Assert.notNull(device,"设备序列号不存在");
        //  设备信息
        records.setDeviceId(device.getId());
        records.setDeviceName(device.getName());
        records.setSerialNumber(device.getSerialNumber());
        records.setInstallPath(device.getInstallPath());
        records.setIsOut(device.getIsOut());
        //  小区信息
        records.setResidentialId(device.getXqId());
        records.setUnitId(device.getUnitId());
        //  机构信息
        records.setOrgPosition(device.getOrgPosition());
        records.setEstatePosition(device.getEstatePosition());
        records.setRootOrgId(device.getRootOrgId());
        records.setAccessDate(new Date());
        //  保存出入记录
        ResultBean<Boolean> resultBean = this.accessRecordsFeign.addDHAccessRecords(records);
        return resultBean;
    }

    /**
     * 功能描述: 分页获取服务人员人脸Id列表
     * @param pageBean {
     *      dto     :   设备序列号,必填
     *      current :   查询页码,默认1
     *      size    :   每页的条数,默认10
     * }
     * @return ResultBean<Page>
     *
     *
     */
    @PostMapping(value = "/estate/pagingQuery/server/face")
    public ResultBean<Page> pagingQueryServerUserFaceId(@RequestBody PageBean<UserInfoDto,String> pageBean){
        Assert.hasText(pageBean.getDto(),"设备序列号不能为空");
        //  获取设备信息
        Device device = this.deviceFeign.getEntityBySerialNumber(pageBean.getDto());
        Assert.notNull(device,"设备序列号不存在");
        pageBean.setDto(device.getXqId().toString());
        if(device.getDeviceFactory() != null && device.getDeviceFactory().equals(DeviceConstants.DEVICE_FACTROY_JVT)){
            Page<UserInfoDto> page = this.baseUserFeign.pagingQueryServerUserEnable(pageBean);
            return new ResultBean<>(ResultEnum.SUCCESS,page);
        }
        Page<UserInfoDto> page = this.baseUserFeign.pagingQueryServerUser(pageBean);
        return new ResultBean<>(ResultEnum.SUCCESS,page);
    }

    /**
     * 功能描述: 分页获取住户人脸Id列表
     * @param pageBean {
     *      dto     :   设备序列号,必填
     *      current :   查询页码,默认1
     *      size    :   每页的条数,默认10
     * }
     * @return ResultBean<Page>
     *
     *
     */
    @PostMapping(value = "/estate/pagingQuery/user/face")
    public ResultBean<Page> pagingQueryUserFaceId(@RequestBody PageBean<UserInfoDto,String> pageBean){
        Assert.hasText(pageBean.getDto(),"设备序列号不能为空");
        //  获取设备信息
        Device device = this.deviceFeign.getEntityBySerialNumber(pageBean.getDto());
        Assert.notNull(device,"设备序列号不存在");
        pageBean.setDto(device.getOrgPosition());
        if(device.getDeviceFactory() != null && device.getDeviceFactory().equals(DeviceConstants.DEVICE_FACTROY_JVT)){
            Page<UserInfoDto> page = this.baseUserFeign.pagingQueryUserEnable(pageBean);
            return new ResultBean<>(ResultEnum.SUCCESS, page);
        }
        Page<UserInfoDto> page = this.baseUserFeign.pagingQueryUser(pageBean);
        return new ResultBean<>(ResultEnum.SUCCESS,page);
    }

    /**
     * 功能描述: 分页获取卡列表
     * @param pageBean {
     *      dto     :   设备序列号,必填
     *      current :   查询页码,默认1
     *      size    :   每页的条数,默认10
     * }
     * @return ResultBean<Page>
     *
     *
     */
    @PostMapping(value = "/estate/pagingQuery/card")
    public ResultBean<Page> pagingQueryCard(@RequestBody PageBean<AccessCard, String> pageBean){
        Assert.hasText(pageBean.getDto(),"设备序列号不能为空");
        //  获取设备信息
        Device device = this.deviceFeign.getEntityBySerialNumber(pageBean.getDto());
        Assert.notNull(device,"设备序列号不存在");
        PageBean<AccessCard, Device> parameter = new PageBean<>();
        parameter.setCurrent(pageBean.getCurrent());
        parameter.setSize(pageBean.getSize());
        parameter.setDto(device);
        Page<AccessCard> page;
        if(device.getDeviceFactory() != null && device.getDeviceFactory().equals(DeviceConstants.DEVICE_FACTROY_JVT)){
            page = this.accessCardFeign.enablePagingQuery(parameter);
        }else{
            page = this.accessCardFeign.pagingQuery(parameter);
        }
        page.getRecords().forEach(card -> {
            String userId = card.getUserId();
            if (null != card.getType() && card.getType().equals(OperationConstant.FOUR)){
                card.setUserId(UserFlagConstant.SERVER_USER_FLAG + userId);
            }else {
                card.setUserId(UserFlagConstant.USER_FLAG + userId);
            }
        });
        return new ResultBean<>(ResultEnum.SUCCESS,page);
    }

    /**
     * 功能描述: 分页获取开门密码记录
     * @param pageBean 查询条件
     * @return ResultBean<Page>
     *
     *
     */
    @PostMapping(value = "/estate/pagingQuery/pwd")
    public ResultBean<Page> pagingQueryPwd(@RequestBody PageBean<GuestAuthorize,String> pageBean){
        Assert.hasText(pageBean.getDto(),"设备序列号不能为空");
        //  获取设备信息
        Device device = this.deviceFeign.getEntityBySerialNumber(pageBean.getDto());
        Assert.notNull(device,"设备序列号不存在");
        //  构建查询条件
        GuestAuthorizeDto dto = new GuestAuthorizeDto();
        dto.setPage(pageBean);
        dto.setOrgPosition(device.getOrgPosition());
        dto.setSelectEndDate(new Date());
        dto.setEnableType(0);
        //  查询开门密码记录
        Page<GuestAuthorize> page = this.guestAuthorizeFeign.showEffectiveGuestAuthorizeList(dto);
        return new ResultBean<>(ResultEnum.SUCCESS,page);
    }

    /**
     * 获取房间呼叫组Id
     * @param account 查询条件
     * @return ResultBean<String>
     */
    @PostMapping(value = "/estate/getRoomCallGroupId")
    public ResultBean<Object> getRoomCallGroupId(@RequestBody VideoCallAccount account){
        Assert.hasText(account.getSerialNumber(),"设备序列号不能为空");
        Assert.notNull(account.getRoomNumber(),"门牌号不能为空");
        //  获取设备信息
        Device device = this.deviceFeign.getEntityBySerialNumber(account.getSerialNumber());
        Assert.notNull(device,"设备序列号有误");
        Assert.notNull(device.getXqId(),"该设备尚未绑定小区,请联系管理员");
        //  判断设备是否绑定在单元下
        if (null == device.getUnitId()){
            Assert.notNull(account.getUnitNumber(),"单元编号不能为空");
            //  获取单元信息
            Unit unit = this.unitFeign.getByUnitNumberAndXqId(device.getXqId(), account.getUnitNumber());
            Assert.notNull(unit,"单元编号不存在");
            account.setUnitId(unit.getId());
        }else {
            account.setUnitId(device.getUnitId());
        }
        account.setXqId(device.getXqId());
        //  获取房间组Id
        return this.videoCallAccountFeign.getRoomCallGroupId(account);
    }

    /**
     * 获取设备对讲账号
     * @param account 对讲账号
     * @return ResultBean<VideoCallAccount>
     */
    @PostMapping(value = "/estate/getCallAccount")
    public ResultBean<VideoCallAccount> getCallAccount(@RequestBody VideoCallAccount account){
        Assert.hasText(account.getSerialNumber(),"设备序列号不能为空");
        return this.videoCallAccountFeign.getDeviceCallAccount(account.getSerialNumber());
    }

    /**
     * 获取管理机呼叫组Id
     * @param account 查询条件
     * @return ResultBean<Object>
     */
    @PostMapping(value = "/estate/getManageGroupId")
    public ResultBean<Object> getManageGroupId(@RequestBody VideoCallAccount account){
        Assert.hasText(account.getSerialNumber(),"设备序列号不能为空");
        //  获取设备信息
        Device device = this.deviceFeign.getEntityBySerialNumber(account.getSerialNumber());
        Assert.notNull(device,"设备序列号有误");
        Assert.notNull(device.getXqId(),"该设备尚未绑定小区,请联系管理员");
        account.setXqId(device.getXqId());
        //  获取房间组Id
        return this.videoCallAccountFeign.getManageCallGroupId(account);
    }
}
