package com.qiuguo.iot.user.api.controller.device;

import cn.hutool.crypto.digest.MD5;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.qiuguo.iot.base.constans.RedisConstans;
import com.qiuguo.iot.base.enums.DeviceTypeEnum;
import com.qiuguo.iot.base.enums.OrderByEnum;
import com.qiuguo.iot.base.enums.YesNo;
import com.qiuguo.iot.base.utils.StringUtils;
import com.qiuguo.iot.data.entity.device.DeviceInfoEntity;
import com.qiuguo.iot.data.entity.device.DeviceUserTalkRecordEntity;
import com.qiuguo.iot.data.request.device.DeviceInfoRequest;
import com.qiuguo.iot.data.request.device.DeviceUserTalkRecordRequest;
import com.qiuguo.iot.data.resp.device.DeviceTalkRecordResp;
import com.qiuguo.iot.data.resp.device.DeviceUserTalkRecordResp;
import com.qiuguo.iot.data.service.device.DeviceBatchService;
import com.qiuguo.iot.data.service.device.DeviceInfoService;
import com.qiuguo.iot.data.service.device.DeviceUserTalkRecordService;
import com.qiuguo.iot.third.service.TuyaDeviceConnector;
import com.qiuguo.iot.user.api.resp.device.DeviceInitResp;
import lombok.extern.slf4j.Slf4j;
import org.hswebframework.web.api.crud.entity.PagerResult;
import org.hswebframework.web.exception.BusinessException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.ReactiveStringRedisTemplate;
import org.springframework.data.redis.core.ReactiveValueOperations;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Mono;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@RestController
@Slf4j
@RequestMapping("/device")
public class DeviceController {
    @Value("${device.key}")
    private String key;
    @Value("${device.checkTimeout}")
    private Boolean checkTimeout;
    @Autowired
    private DeviceInfoService deviceInfoService;

    @Resource
    private DeviceBatchService deviceBatchService;

    @Resource
    private TuyaDeviceConnector tuyaDeviceConnector;

    @Resource
    private ReactiveStringRedisTemplate reactiveStringRedisTemplate;

    @Resource
    private DeviceUserTalkRecordService deviceUserTalkRecordService;


    @Value("${device.timeout}")
    private Long timeOut;//2分钟
    @GetMapping("/init")
    public Mono<DeviceInitResp> deviceInit(@RequestParam String wifiMac, @RequestParam String btMac,
                                           @RequestParam Integer type, @RequestParam Long time,
                                           @RequestParam String signature){
        //deviceInfoService.
        Long now = System.currentTimeMillis();
        if(checkTimeout && now - time > timeOut){
            //超时
            log.info("请求过期");
            BusinessException ex = new BusinessException("请求已失效");
            return Mono.error(ex);
        }
        //设备类型是否匹配暂时不做限制
        DeviceTypeEnum entryTypeEnum = DeviceTypeEnum.getEnumWithCode(type);
        if(entryTypeEnum == null){
            log.info("不支持的设备类型");
            BusinessException ex = new BusinessException("不支持的设备类型");
            return Mono.error(ex);
        }
        //验签
        String wifiMd5 = MD5.create().digestHex(wifiMac).toUpperCase();
        String btMd5 = MD5.create().digestHex(btMac).toUpperCase();
        String typeMd5 = MD5.create().digestHex(type.toString()).toUpperCase();
        String md5 = MD5.create().digestHex(wifiMd5 + btMd5 + typeMd5 + time + key).toUpperCase();
        if (!md5.equals(signature)) {
            //
            //验签失败
            log.info("验签失败");
            BusinessException ex = new BusinessException("验签失败");
            return Mono.error(ex);
        }

        DeviceInfoRequest request = new DeviceInfoRequest();
        request.setWifiMac(wifiMac);
        request.setBtMac(btMac);
        Mono<DeviceInfoEntity> mono = deviceInfoService.selectDeviceInfoByRequest(request);

        return mono.defaultIfEmpty(new DeviceInfoEntity()).flatMap(entity -> {
            Mono mono1 = null;
            if(entity.getId() == null){
                entity.setWifiMac(wifiMac);
                entity.setBtMac(btMac);
                entity.setBatchId(1l);
                entity.setName(entryTypeEnum.getName());
                entity.setDeviceType(type);
                entity.setKey( com.qiuguo.iot.base.utils.StringUtils.getRandomStr(10));//生成key
                DateTimeFormatter df = DateTimeFormatter.ofPattern("yyMMddHHmmss");
                entity.setSn("QG" + entryTypeEnum.getSn() +df.format(LocalDateTime.now()) + StringUtils.getRandomStr(3));
                mono1 = deviceInfoService.insertDeviceInfo(entity);
            }else{
                entity.setKey( com.qiuguo.iot.base.utils.StringUtils.getRandomStr(10));//重新生成Key
                mono1 = deviceInfoService.updateDeviceInfoById(entity);


            }
            return mono1.map(m ->{
                return entity;
            });
        }).map(o -> {
            DeviceInfoEntity deviceInfoEntity = (DeviceInfoEntity)o;
            ReactiveValueOperations<String, String> operations = reactiveStringRedisTemplate.opsForValue();
            operations.set(RedisConstans.DEVICE_INFO + deviceInfoEntity.getSn()
                    , JSONObject.toJSONString(deviceInfoEntity)
                    , RedisConstans.ONE_HOUR).subscribe();
            DeviceInitResp resp = new DeviceInitResp();
            resp.setKey(deviceInfoEntity.getKey());
            resp.setSn(deviceInfoEntity.getSn());
            return resp;
        });


    }

    @PostMapping("/talk/records")
    public Mono<PagerResult<DeviceTalkRecordResp>> talkRecords(@RequestBody DeviceUserTalkRecordRequest request){

        if(StringUtils.isNotEmpty(request.getOrder()) && StringUtils.isNotEmpty(request.getOrder())){
            //默认按照时间倒叙排序
            request.setOrder("create_time");
            request.setOrder(OrderByEnum.DESC.getName());
        }
        return deviceUserTalkRecordService.selectDeviceUserTalkRecordsByRequest(request)
                .map(deviceUserTalkRecordEntityPagerResult -> {
                    PagerResult<DeviceTalkRecordResp> pagerResult = new PagerResult<>();
                    pagerResult.setTotal(deviceUserTalkRecordEntityPagerResult.getTotal());
                    pagerResult.setPageSize(deviceUserTalkRecordEntityPagerResult.getPageSize());
                    pagerResult.setPageIndex(deviceUserTalkRecordEntityPagerResult.getPageIndex());
                    List<DeviceTalkRecordResp> list = new ArrayList<>();
                    for (DeviceUserTalkRecordEntity d  :deviceUserTalkRecordEntityPagerResult.getData()
                         ) {
                        list.add(new DeviceTalkRecordResp(d, YesNo.YES.getCode()));
                        list.add(new DeviceTalkRecordResp(d, YesNo.NO.getCode()));
                    }

                    pagerResult.setData(list);

                    return pagerResult;
                });
    }


    @GetMapping("/deviceBySnId")
    public Mono<JSONArray> aa(@RequestParam("sn") String sn){
        return Mono.just(tuyaDeviceConnector.getByid(sn));
    }
}
