package com.yuchen.saas.park.service.controller.device;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import com.google.protobuf.ServiceException;
import com.yuchen.saas.park.api.entity.device.PmgBatSmartEquipment;
import com.yuchen.saas.park.api.entity.park.PmgBatParkCompany;
import com.yuchen.saas.park.api.entity.park.PmgBtnDeviceOther;
import com.yuchen.saas.park.api.vo.park.DeviceAndParkingVo;
import com.yuchen.saas.park.api.vo.park.PmgBatSmartEquipmentPointVo;
import com.yuchen.saas.park.api.vo.park.PmgBatSmartEquipmentVo;
import com.yuchen.saas.park.service.service.IParkCompanyService;
import com.yuchen.saas.park.service.service.PmgBatParkPerceiveService;
import com.yuchen.saas.park.service.service.PmgBatSmartEquipmentService;
import com.yuchen.saas.park.service.service.PmgBtnDeviceOtherService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.nest.springwrap.core.mp.support.Condition;
import org.nest.springwrap.core.mp.support.Query;
import org.nest.springwrap.core.tool.api.R;
import org.nest.springwrap.core.tool.utils.Func;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.List;

/**
 * @author 刘通
 * @date 2020/12/30 17:42
 */
@Slf4j
@RestController
@AllArgsConstructor
@RequestMapping("/smartEquipment")
@Api(value = "智慧消防设备信息对象", tags = "智慧消防设备信息接口")
public class PmgBatSmartEquipmentController {
    @Autowired
    private PmgBatSmartEquipmentService pmgBatSmartEquipmentService;
    @Autowired
    private PmgBtnDeviceOtherService pmgBtnDeviceOtherService;
    @Autowired
    private IParkCompanyService iParkCompany;

    @Resource
    private PmgBatParkPerceiveService pmgBatParkPerceiveService;

    private final static Logger LOGGER = LoggerFactory.getLogger(PmgBatSmartEquipmentController.class);
    /**
     * 详情
     */
    @GetMapping("/detail")
    @ApiOperationSupport(order = 1)
    @ApiOperation(value = "详情", notes = "园区空间主题类型信息")
    public R<PmgBatSmartEquipment> detail(PmgBatSmartEquipment pmgBatSmartEquipment) {
        PmgBatSmartEquipment detail = pmgBatSmartEquipmentService.getOne(Condition.getQueryWrapper(pmgBatSmartEquipment));
        return R.data(detail);
    }

    /**
     * 通过 productKey 和 deviceName 获取设备及站点信息
     * @param productKey
     * @param deviceName
     * @return
     */
    @GetMapping("/getDetailsByPkAndDN")
    @ApiOperationSupport(order = 1)
    @ApiOperation(value = "详情", notes = "园区空间主题类型信息")
    public R<PmgBatSmartEquipmentVo> getDetailsByPkAndDN(String productKey, String deviceName) {
        PmgBatSmartEquipmentVo detail = pmgBatSmartEquipmentService.getDetailsByPkAndDN(productKey, deviceName);
        return R.data(detail);
    }
    /**
     * 通过product key 和 device name 查询详情信息
     */
    @GetMapping("/getDetails")
    @ApiOperationSupport(order = 2)
    @ApiOperation(value = "详情", notes = "园区空间主题类型信息")
    public R<PmgBatSmartEquipment> getDetails(@RequestParam String productKey, @RequestParam String deviceName) throws ServiceException {
        PmgBatSmartEquipment detail = pmgBatSmartEquipmentService.getDetails(productKey, deviceName);
        return R.data(detail);
    }
    /**
     * 通过product key 获取设备列表
     */
    @GetMapping("/getDevices")
    @ApiOperationSupport(order = 3)
    @ApiOperation(value = "详情", notes = "园区空间主题类型信息")
    public R<List<PmgBatSmartEquipment>> getDevices(String productKey) throws ServiceException {
        List<PmgBatSmartEquipment> detail = pmgBatSmartEquipmentService.getDevices(productKey);
        return R.data(detail);
    }
    /**
     * 分页 园区空间主题类型信息
     */
    @GetMapping("/list")
    @ApiOperationSupport(order = 3)
    @ApiOperation(value = "分页", notes = "园区空间主题类型信息")
    public R<IPage<PmgBatSmartEquipment>> list(PmgBatSmartEquipment pmgBatSmartEquipment, Query query) {
        IPage<PmgBatSmartEquipment> pages = pmgBatSmartEquipmentService.page(Condition.getPage(query),
                new LambdaQueryWrapper<PmgBatSmartEquipment>()
                        .eq(Func.isNotEmpty(pmgBatSmartEquipment.getParkId()), PmgBatSmartEquipment::getParkId,
                                pmgBatSmartEquipment.getParkId())
                        .like(Func.isNotEmpty(pmgBatSmartEquipment.getName()), PmgBatSmartEquipment::getName,
                                pmgBatSmartEquipment.getName())
                        .eq(Func.isNotEmpty(pmgBatSmartEquipment.getProductKey()), PmgBatSmartEquipment::getProductKey,
                                pmgBatSmartEquipment.getProductKey())
                        .eq(Func.isNotEmpty(pmgBatSmartEquipment.getDeviceName()), PmgBatSmartEquipment::getDeviceName,
                                pmgBatSmartEquipment.getDeviceName())
                        .orderByDesc(PmgBatSmartEquipment::getCreateTime)
        );
        return  R.data(pages);
    }
    /**
     * 分页 园区空间主题类型信息
     */
    @GetMapping("/getAll")
    @ApiOperationSupport(order = 3)
    @ApiOperation(value = "分页", notes = "园区空间主题类型信息")
    public R<List<PmgBatSmartEquipmentVo>> list() {
        List<PmgBatSmartEquipmentVo> allList = pmgBatSmartEquipmentService.getDetailAll();
        return  R.data(allList);
    }

    /**
     * 新增 园区空间主题类型信息
     */
    @PostMapping("/save")
    @ApiOperationSupport(order = 4)
    @ApiOperation(value = "新增", notes = "传入园区空间主题类型信息")
    public R save(@Valid @RequestBody PmgBatSmartEquipmentVo pmgBatSmartEquipmentVo) throws ServiceException {
        return submit(pmgBatSmartEquipmentVo);
    }
    /**
     * 新增或修改
     */
    @PostMapping("/submit")
    @ApiOperationSupport(order = 5)
    @ApiOperation(value = "新增或修改", notes = "传入园区空间主题类型信息")
    public R submit(@Valid @RequestBody PmgBatSmartEquipmentVo pmgBatSmartEquipmentVo) throws ServiceException {
        if(Func.isEmpty(pmgBatSmartEquipmentVo)) {
            return R.error("请求参数为空！");
        }
        // 获取公司ID
        String companyId = String.valueOf(pmgBatSmartEquipmentVo.getCompanyId());
        LOGGER.info("companyId:" + companyId);
        // 获取设备信息
        PmgBatSmartEquipment pmgBatSmartEquipment = new PmgBatSmartEquipment();

        BeanUtils.copyProperties(pmgBatSmartEquipmentVo, pmgBatSmartEquipment);

        if(Func.isEmpty(pmgBatSmartEquipment)) {
            return R.error("设备信息为空！");
        }
        LambdaQueryWrapper<PmgBatSmartEquipment> parkSmartWrapper = Wrappers.lambdaQuery();
        LambdaQueryWrapper<PmgBtnDeviceOther> deviceOtherWrapper = Wrappers.lambdaQuery();
        LambdaQueryWrapper<PmgBatParkCompany> parkCompanyWrapper = Wrappers.lambdaQuery();
        /**
         * 判断ID 是否存在，存在说明是更新，不存在说明是新增，首先判断是否已存在该设备，如果存在不新增。
         * （判断是否已有该设备：通过product key 和 device name 查询设备，看是否已存在要添加的设备）
         */
        if(Func.isEmpty(pmgBatSmartEquipment.getId())) {
            int getSmartEq = pmgBatSmartEquipmentService.count(parkSmartWrapper.eq(PmgBatSmartEquipment::getDeviceName,
                    pmgBatSmartEquipment.getDeviceName()).eq(PmgBatSmartEquipment::getProductKey,
                    pmgBatSmartEquipment.getProductKey()));
            if(getSmartEq > 0) {
                return R.error("设备已存在!");
            }
        } else { // id 不为空，说明是更新。
            // 通过设备ID查询设备绑定信息
            List<PmgBtnDeviceOther> otherList = pmgBtnDeviceOtherService.list(deviceOtherWrapper.eq(PmgBtnDeviceOther::getDeviceId, pmgBatSmartEquipment.getId()));
            if(Func.isNotEmpty(otherList) && otherList.size() > 0) {
                boolean removeOtherService = true;
                for(PmgBtnDeviceOther deviceOther : otherList) {
                    // 通过other_id 查询公司表，如果有公司信息，删除关联表这条数据。
                    int companyCount = iParkCompany.count(parkCompanyWrapper.eq(PmgBatParkCompany::getId, deviceOther.getOtherId()));
                    if(companyCount > 0) {
                        // 删除当前的设备关联信息
                        removeOtherService = pmgBtnDeviceOtherService.removeById(deviceOther.getId());
                        if(!removeOtherService) {
                            break;
                        }
                    }
                }
                if(!removeOtherService) {
                    return R.error("更新删除设备关联信息失败!");
                }
            }
        }
        Boolean saveSmartEqueipment = pmgBatSmartEquipmentService.saveOrUpdate(pmgBatSmartEquipment);
        if(!saveSmartEqueipment) {
            return R.error("保存设备失败！");
        }
        // 查询设备（因为ID有可能为空）
        PmgBatSmartEquipment getOne = pmgBatSmartEquipmentService.getOne(parkSmartWrapper.eq(PmgBatSmartEquipment::getDeviceName,
                pmgBatSmartEquipment.getDeviceName()).eq(PmgBatSmartEquipment::getProductKey,
                pmgBatSmartEquipment.getProductKey()));
        if(Func.isNotEmpty(companyId) && Func.isNotEmpty(getOne)) {
            // 将设备与公司绑定
            PmgBtnDeviceOther saveDeviceOther = new PmgBtnDeviceOther();
            saveDeviceOther.setOtherId(companyId);
            saveDeviceOther.setDeviceId(String.valueOf(getOne.getId()));
            LOGGER.info("saveDeviceOther:" + saveDeviceOther);
            boolean saveDeviceOtherBl = pmgBtnDeviceOtherService.save(saveDeviceOther);
            if(!saveDeviceOtherBl) {
                return R.error("保存设备成功，保存设备与公司关联信息失败！");
            }
        }
        // 更新设备信息缓存
        pmgBatParkPerceiveService.updateDeviceCash(pmgBatSmartEquipment);
        return R.status(saveSmartEqueipment);
    }
    /**
     * 修改
     */
    @SneakyThrows
    @PutMapping("/update")
    @ApiOperationSupport(order = 6)
    @ApiOperation(value = "修改", notes = "传入园区空间主题类型信息")
    public R update(@Valid @RequestBody PmgBatSmartEquipmentVo pmgBatSmartEquipment) {
        return R.status(pmgBatSmartEquipmentService.updateById(pmgBatSmartEquipment));
    }
    /**
     * 删除 园区空间主题类型信息
     */
    @DeleteMapping("/remove")
    @ApiOperationSupport(order = 7)
    @ApiOperation(value = "逻辑删除", notes = "传入ids")
    public R remove(@ApiParam(value = "主键集合", required = true) @RequestParam String ids) {

        List<Long> idsList = Func.toLongList(ids);

        boolean deleteOther = true;
        if(Func.isNotEmpty(idsList) && idsList.size() > 0) {
            LambdaQueryWrapper<PmgBtnDeviceOther> deviceOtherWrapper = Wrappers.lambdaQuery();
            for(Long id : idsList) {
                /**
                 * 删除设备绑定信息
                 */
                List<PmgBtnDeviceOther> otherList = pmgBtnDeviceOtherService.list(deviceOtherWrapper.eq(PmgBtnDeviceOther::getDeviceId, id));
                if(Func.isNotEmpty(otherList) && otherList.size() > 0) {
                    deleteOther = pmgBtnDeviceOtherService.deleteList(otherList);
                    if(!deleteOther) {
                        deleteOther = false;
                        break;
                    }
                }
            }
        }
        if(!deleteOther) {
            return R.error("删除设备关联信息失败！");
        }
        boolean removesmartEquipment = pmgBatSmartEquipmentService.deleteLogic(Func.toLongList(ids));
        if(!removesmartEquipment) {
            return R.error("删除设备信息失败！");
        }
        return R.data("操作成功");
//        return R.status(pmgBatSmartEquipmentService.deleteLogic(Func.toLongList(ids)));
    }

    /**
     * 根据 productKey 获取设备列表
     * @param productKey 可以用逗号隔开
     * @return
     */
    @GetMapping("/getDevicesListByKey")
    @ApiOperationSupport(order = 8)
    @ApiOperation(value = "获取设备列表", notes = "获取设备列表")
    public R<List<PmgBatSmartEquipment>> getDevicesListByKey(String productKey){
        List<PmgBatSmartEquipment> list = pmgBatSmartEquipmentService.getDevicesListByKey(productKey);
        return R.data(list);
    }

    /**
     * 根据 productKey 获取设备列表
     * @param productKey 可以用逗号隔开
     * @return
     */
    @GetMapping("/getDevicesListByKeyFeign")
    @ApiOperationSupport(order = 8)
    @ApiOperation(value = "获取设备列表", notes = "获取设备列表")
    public List<PmgBatSmartEquipment> getDevicesListByKeyFeign(@RequestParam String parkId, @RequestParam String productKey){
        List<PmgBatSmartEquipment> list = pmgBatSmartEquipmentService.getDevicesListByKey(parkId,productKey);
        return list;
    }

    @GetMapping("/getDevicesListByProductKeyFeign")
    @ApiOperationSupport(order = 8)
    @ApiOperation(value = "获取设备列表", notes = "获取设备列表")
    public List<PmgBatSmartEquipment> getDevicesListByKeyFeign( @RequestParam String productKey){
        List<PmgBatSmartEquipment> list = pmgBatSmartEquipmentService.getDevicesListByKey(productKey);
        return list;
    }

    /**
     * 根据 productKey 获取设备列表
     * @param productKey 可以用逗号隔开
     * @return
     */
    @GetMapping("/getDeviceByPKandDn")
    @ApiOperationSupport(order = 8)
    @ApiOperation(value = "获取设备列表", notes = "获取设备列表")
    public PmgBatSmartEquipment getDeviceByPKandDn(@RequestParam String deviceName, @RequestParam String productKey){
        PmgBatSmartEquipment equipment = pmgBatSmartEquipmentService.getOne(Wrappers.<PmgBatSmartEquipment>lambdaQuery()
                .select(PmgBatSmartEquipment::getParkId, PmgBatSmartEquipment::getTenantId,PmgBatSmartEquipment::getPlanePosition)
                .eq(PmgBatSmartEquipment::getProductKey, productKey)
                .eq(PmgBatSmartEquipment::getDeviceName, deviceName));
        return equipment;
    }

    @GetMapping("/getDeviceFeign")
    @ApiOperationSupport(order = 8)
    @ApiOperation(value = "获取设备详情", notes = "获取设备详情")
    public PmgBatSmartEquipment getDeviceFeign(@RequestParam String deviceName, @RequestParam String productKey){
        PmgBatSmartEquipment equipment = pmgBatSmartEquipmentService.getOne(Wrappers.<PmgBatSmartEquipment>lambdaQuery()
                .eq(PmgBatSmartEquipment::getProductKey, productKey)
                .eq(PmgBatSmartEquipment::getDeviceName, deviceName));
        return equipment;
    }

    /**
     * 修改设备在离线状态
     * @param equipmentList 设备信息列表
     * @return
     */
    @PostMapping("/updateBatchByIdFeign")
    @ApiOperationSupport(order = 3)
    @ApiOperation(value = "修改设备在离线状态", notes = "修改设备在离线状态")
    public boolean updateBatchByIdFeign(@RequestBody String equipmentList){
        List<PmgBatSmartEquipment> list = JSON.parseArray(equipmentList,PmgBatSmartEquipment.class);
        return pmgBatSmartEquipmentService.updateBatchById(list);
    }

    /**
     * 根据 productKey 和 deviceName 获取抓拍机设备信息+停车场信息+出入口信息+车道信息
     * @param productKey 产品key
     * @param deviceName 产品名
     * @return
     */
    @GetMapping("/getDeviceAndParking")
    @ApiOperationSupport(order = 8)
    @ApiOperation(value = "获取设备列表", notes = "获取设备列表")
    public R<DeviceAndParkingVo> getDeviceAndParking(@RequestParam String productKey, @RequestParam String deviceName){
        DeviceAndParkingVo deviceAndParkingVo = pmgBatSmartEquipmentService.getDeviceAndParking(productKey, deviceName);
        return R.data(deviceAndParkingVo);
    }

    /**************************  3d/bi start ********************************/

    /**
     * 根据园区id查询设备点位列表
     * @param parkId
     * @return
     */
    @GetMapping("/getEquipmentPointList")
    @ApiOperationSupport(order = 8)
    @ApiOperation(value = "设备点位列表", notes = "设备点位列表")
    public R<List<PmgBatSmartEquipmentPointVo>> selectEquipmentPoint(@RequestParam Long parkId){
        return R.data(pmgBatSmartEquipmentService.selectEquipmentPoint(parkId));
    }

    /**
     * 获取没有被绑定的人脸识别设备
     * @param idList
     * @param productKey
     * @return
     */
    @GetMapping("/getListNotBindByIds")
    @ApiOperationSupport(order = 9)
    @ApiOperation(value = "获取没有被绑定的人脸识别设备", notes = "获取没有被绑定的人脸识别设备")
    public R<List<PmgBatSmartEquipment>> getListNotBindByIds(@RequestParam List<Long> idList,@RequestParam String productKey,@RequestParam String parkId){
        return R.data(pmgBatSmartEquipmentService.getListNotBindByIds(idList, productKey, parkId));
    }

    /**
     * 获取门禁设备列表
     * @return
     */
    @GetMapping("/getEquipmentList")
    @ApiOperationSupport(order = 10)
    @ApiOperation(value = "获取门禁设备列表", notes = "获取门禁设备列表")
    public R<List<PmgBatSmartEquipment>> getEquipmentList(){
        return R.data(pmgBatSmartEquipmentService.list(new LambdaQueryWrapper<PmgBatSmartEquipment>()
                .eq(PmgBatSmartEquipment::getProductKey,"Fsod5zVVEfCLJXTJ")
                .orderByDesc(PmgBatSmartEquipment::getCreateTime)));
    }

}
