package com.xy.open;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.xy.annotate.RestMappingController;
import com.xy.annotation.Open;
import com.xy.bean.OpenContext;
import com.xy.bean.ServiceContext;
import com.xy.dto.CommandMqtt;
import com.xy.dto.DeviceSysinfoDto;
import com.xy.dto.OpenPlatformConfigDto;
import com.xy.entity.DeviceInfo;
import com.xy.exception.ServiceException;
import com.xy.open.dto.DeviceOpenApiDTO;
import com.xy.open.vo.DeviceOpenApiVO;
import com.xy.service.DeviceInfoServiceImpl;
import com.xy.service.DeviceSysinfoServiceImpl;
import com.xy.service.MqttService;
import com.xy.service.OpenPlatformConfigService;
import com.xy.utils.PageBean;
import com.xy.utils.R;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;

import javax.validation.Valid;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static com.xy.utils.PlusBeans.toIPage;
import static com.xy.utils.PlusBeans.toPageBean;

/**
 * 开放api
 */

@Slf4j
@Service
@Api(tags = "设备API")
@RequiredArgsConstructor
@RestMappingController("/openApi")
public class DeviceOpenApiService {

    private final DeviceInfoServiceImpl deviceInfoService;
    private final OpenPlatformConfigService openPlatformConfigService;
    private final MqttService mqttService;
    private final DeviceSysinfoServiceImpl deviceSysinfoService;


    @ApiOperation(value = "获取商户设备列表", notes = "获取商户设备列表")
    @Open(value = "device.page.get", version = "1.0", permission = true)
    @PostMapping("/device/page/get")
    public PageBean<DeviceOpenApiVO.DeviceList> devicePageGet(@RequestBody @Valid DeviceOpenApiDTO.DeviceListGet dto) {
        OpenContext oct = ServiceContext.getCurrentContext().getOpenContext();
        String appId = oct.getAppId();
        boolean b = R.feignCheckData(openPlatformConfigService.checkAuthByMercCode(new OpenPlatformConfigDto.CheckAuth().setAppId(appId).setMercCodes(dto.getMercCodes())));
        if (!b) {
            throw new ServiceException("您传入的商户编码中包含非法编码！");
        }
        PageBean pageBean = dto.getPage();
        LambdaQueryWrapper<DeviceInfo> lqw = Wrappers.<DeviceInfo>lambdaQuery()
                .in(DeviceInfo::getMercCode, dto.getMercCodes()
                );
        IPage<DeviceInfo> iPage = deviceInfoService.page(toIPage(pageBean), lqw);
        PageBean<DeviceOpenApiVO.DeviceList> pageData = toPageBean(DeviceOpenApiVO.DeviceList.class, iPage);
        List<DeviceOpenApiVO.DeviceList> records = pageData.getRecords();
        if (CollUtil.isNotEmpty(records)) {
            List<Long> deviceIds = records.stream().map(DeviceOpenApiVO.DeviceList::getDeviceId).collect(Collectors.toList());
            List<DeviceSysinfoDto.Vo> sysInfoVos = R.feignCheckData(deviceSysinfoService.list(new DeviceSysinfoDto.SelectList().setDeviceIds(deviceIds)));
            Map<Long, DeviceSysinfoDto.Vo> deviceSysInfoMap = sysInfoVos.stream().collect(Collectors.toMap(DeviceSysinfoDto.Vo::getDeviceId, v -> v));
            for (DeviceOpenApiVO.DeviceList record : records) {
                Long deviceId = record.getDeviceId();
                DeviceSysinfoDto.Vo sys = deviceSysInfoMap.get(deviceId);
                if (sys != null) {
                    record.setDeviceModel(StrUtil.isEmpty(sys.getDeviceModel()) ? "" : sys.getDeviceModel());
                }
            }
            pageBean.setRecords(records);
        }
        return pageData;
    }

    @ApiOperation(value = "设备操作", notes = "设备操作（开打印机门锁：openPrinterLock）")
    @Open(value = "device.operate", version = "1.0", permission = true)
    @PostMapping("/device/operate")
    public DeviceOpenApiDTO.DeviceOperateResult deviceOperate(@RequestBody @Valid DeviceOpenApiDTO.DeviceOperate dto) {
        DeviceOpenApiDTO.DeviceOperateResult result = new DeviceOpenApiDTO.DeviceOperateResult();
        OpenContext oct = ServiceContext.getCurrentContext().getOpenContext();
        String appId = oct.getAppId();
        List<Long> mercIds = R.feignCheckData(openPlatformConfigService.getMercIdsByAppId(new OpenPlatformConfigDto.QueryByApp().setAppId(appId)));
        if (CollUtil.isEmpty(mercIds)) {
            throw new ServiceException("尚未分配商户，请联系平台客服!");
        }
        Long deviceId = dto.getDeviceId();
        DeviceInfo deviceInfo = deviceInfoService.getById(deviceId);
        if (deviceInfo == null) {
            throw new ServiceException("设备不存在!");
        }
        if (!CollUtil.contains(mercIds, deviceInfo.getMercId())) {
            throw new ServiceException("您没有权限操作该设备!");
        }
        String action = dto.getAction();
        if ("openPrinterLock".equals(action)) {
            action = "locker";
        } else {
            throw new ServiceException("未知或不支持的操作类型!");
        }
        List<CommandMqtt> commandMqtts = new ArrayList<>();
        JSONObject templet = new JSONObject();
        templet.putOnce("wkSn", "$wkSn$");
        templet.putOnce("cmdType", "task");
        templet.putOnce("actionType", "issue");
        JSONObject data = new JSONObject();
        data.putOnce("type", action);
        data.putOnce("id", "0");
        data.putOnce("jgh", "1");
        data.putOnce("task", "open");
        templet.putOnce("data", data);
        commandMqtts.add(new CommandMqtt().setDeviceId(deviceId).setTemplet(templet));
        mqttService.senCommand(commandMqtts);
        result.setResult(true);
        return result;
    }

}
