package com.sikey.wa04.business.infrastructure.adapter.dao;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.sikey.wa04.business.domain.adapter.DeviceQueryAdapter;
import com.sikey.wa04.business.domain.entity.ChildId;
import com.sikey.wa04.business.domain.entity.Device;
import com.sikey.wa04.business.domain.entity.DeviceConfig;
import com.sikey.wa04.business.domain.entity.DeviceId;
import com.sikey.wa04.business.infrastructure.dto.model.DeviceBindModel;
import com.sikey.wa04.business.infrastructure.dto.model.DeviceConfigModel;
import com.sikey.wa04.business.infrastructure.dto.model.DeviceModel;
import com.sikey.wa04.business.infrastructure.repository.DeviceBindRepository;
import com.sikey.wa04.business.infrastructure.repository.DeviceRepository;
import com.sikey.wa04.common.enums.SignalStepBatteryStepEnum;
import com.sikey.wa04.common.enums.VideoCallChannel;
import com.sikey.wa04.common.exception.BusinessException;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 设备查询适配器
 */
@Slf4j
@Component
public class DeviceQueryAdapterImpl implements DeviceQueryAdapter {

    @Resource
    private DeviceRepository deviceRepository;

    @Resource
    private DeviceBindRepository deviceBindRepository;

    @Override
    public Device findByChildId(ChildId cid) throws BusinessException {
        DeviceBindModel deviceBindModel = deviceBindRepository.findByChildId(cid.getId());
        if (deviceBindModel == null) {
            return null;
        }

        DeviceModel deviceModel = deviceRepository.findById(deviceBindModel.getDeviceId())
                .orElseThrow();

        List<DeviceConfigModel> deviceConfigModelList = deviceModel.getDeviceConfigModelList();

        DeviceConfig config = null;
        if (CollectionUtil.isNotEmpty(deviceConfigModelList)) {
            DeviceConfigParser configParser = new DeviceConfigParser(deviceConfigModelList);
            config = new DeviceConfig()
                    .setBattery(configParser.battery())
                    .setSignal(configParser.signal())
                    .setMaxSignal(configParser.maxSignal())
                    .setStepCount(configParser.stepCount())
                    .setStartup(configParser.startup());
        }

        log.info("通过儿童查询设备: {}", JSONUtil.toJsonPrettyStr(deviceConfigModelList));
        return new Device().setId(new DeviceId(deviceModel.getId()))
                .setBinder(deviceBindModel.getChildId())
                .setTicket(deviceModel.getTicket())
                .setHardCode(deviceModel.getHc())
                .setAesKey(deviceModel.getAesKey())
                .setVideoCallChannel(VideoCallChannel.valueOf(deviceModel.getVideoCallChannel()))
                .setActivationTime(deviceModel.getActivationTime())
                .setCreatedAt(deviceModel.getCreatedAt())
                .setUpdatedAt(deviceModel.getUpdatedAt())
                .setDeletedAt(deviceModel.getDeletedAt())
                .setConfig(config)
                .setModel(deviceModel.getModel())
                .setVersion(deviceModel.getVersion());
    }

    /**
     * 查询设备
     *
     * @param ticket
     * @return
     * @throws BusinessException
     */
    @Override
    public Device queryDeviceByTicket(String ticket) throws BusinessException {
        DeviceModel deviceModel = deviceRepository.findByTicket(ticket).
                orElseThrow(() -> new BusinessException(HttpStatus.INTERNAL_SERVER_ERROR.value(), "不存在该设备"));

        Device device = new Device();
        device.setTicket(deviceModel.getTicket());
        device.setId(new DeviceId(deviceModel.getId()));
        return device;
    }

    /**
     * 设备配置解析器
     *
     * @author luoyangwei
     */
    private static class DeviceConfigParser {

        private Map<String, String> deviceConfigMap;

        public DeviceConfigParser(List<DeviceConfigModel> configs) {
            deviceConfigMap = configs.stream().collect(Collectors.toMap(
                    DeviceConfigModel::getKey, DeviceConfigModel::getValue, (existingValue, newValue) -> existingValue));
        }

        public Integer battery() {
            return Integer.parseInt(StrUtil.isEmpty(deviceConfigMap.get(SignalStepBatteryStepEnum.BATTERY.getDescription())) ? "0" : deviceConfigMap.get(SignalStepBatteryStepEnum.BATTERY.getDescription()));
        }

        public Integer signal() {
            return Integer.parseInt(StrUtil.isEmpty(deviceConfigMap.get(SignalStepBatteryStepEnum.SIGNAL.getDescription())) ? "0" : deviceConfigMap.get(SignalStepBatteryStepEnum.SIGNAL.getDescription()));
        }

        public Integer maxSignal() {
            return Integer.parseInt(StrUtil.isEmpty(deviceConfigMap.get(SignalStepBatteryStepEnum.MAX_SIGNAL.getDescription())) ? "0" : deviceConfigMap.get(SignalStepBatteryStepEnum.MAX_SIGNAL.getDescription()));
        }

        public Integer stepCount() {
            return Integer.parseInt(StrUtil.isEmpty(deviceConfigMap.get(SignalStepBatteryStepEnum.STEP.getDescription())) ? "0" : deviceConfigMap.get(SignalStepBatteryStepEnum.STEP.getDescription()));
        }

        public Boolean startup() {
            if (StrUtil.isEmpty(deviceConfigMap.get(SignalStepBatteryStepEnum.STARTUP.getDescription()))) {
                return false;
            } else if (deviceConfigMap.get(SignalStepBatteryStepEnum.STARTUP.getDescription()).equals("1")) {
                return true;
            } else {
                return false;
            }
        }
    }

}
