package org.nl.acs.device.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.IdUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import lombok.AllArgsConstructor;
import org.nl.acs.device.domain.DeviceAssigned;
import org.nl.acs.device.service.DeviceAssignedService;
import org.nl.acs.device.service.dto.DeviceAssignedDto;
import org.nl.acs.device.service.dto.DeviceAssignedQueryParam;
import org.nl.acs.device.service.mapper.DeviceAssignedMapper;
import org.nl.acs.common.base.PageInfo;
import org.nl.acs.common.base.QueryHelpMybatisPlus;
import org.nl.acs.common.base.impl.CommonServiceImpl;
import org.nl.acs.storage_cell.domain.StorageCell;
import org.nl.acs.storage_cell.service.dto.StorageCellDto;
import org.nl.acs.utils.ConvertUtil;
import org.nl.common.utils.FileUtil;
import org.nl.acs.utils.PageUtil;
import org.nl.common.utils.SecurityUtils;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*;

/**
* @author jiaolm
* @date 2023-05-09
*/
@Service
@AllArgsConstructor
// @CacheConfig(cacheNames = DeviceAssignedService.CACHE_KEY)
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class DeviceAssignedServiceImpl extends CommonServiceImpl<DeviceAssignedMapper, DeviceAssigned> implements DeviceAssignedService {

    // private final RedisUtils redisUtils;
    private final DeviceAssignedMapper deviceAssignedMapper;

    @Override
    public PageInfo<DeviceAssignedDto> queryAll(DeviceAssignedQueryParam query, Pageable pageable) {
        IPage<DeviceAssigned> queryPage = PageUtil.toMybatisPage(pageable);
        IPage<DeviceAssigned> page = deviceAssignedMapper.selectPage(queryPage, QueryHelpMybatisPlus.getPredicate(query));
        return ConvertUtil.convertPage(page, DeviceAssignedDto.class);
    }

    @Override
    public List<DeviceAssignedDto> queryAll(DeviceAssignedQueryParam query){
        return ConvertUtil.convertList(deviceAssignedMapper.selectList(QueryHelpMybatisPlus.getPredicate(query)), DeviceAssignedDto.class);
    }

    @Override
    public DeviceAssigned getById(String id) {
        return deviceAssignedMapper.selectById(id);
    }

    @Override
    // @Cacheable(key = "'id:' + #p0")
    public DeviceAssignedDto findById(String id) {
        return ConvertUtil.convert(getById(id), DeviceAssignedDto.class);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int insert(DeviceAssignedDto resources) {
        DeviceAssigned entity = ConvertUtil.convert(resources, DeviceAssigned.class);
        return deviceAssignedMapper.insert(entity);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int updateById(DeviceAssignedDto resources){
        DeviceAssigned entity = ConvertUtil.convert(resources, DeviceAssigned.class);
        int ret = deviceAssignedMapper.updateById(entity);
        // delCaches(resources.id);
        return ret;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int removeByIds(Set<String> ids){
        // delCaches(ids);
        return deviceAssignedMapper.deleteBatchIds(ids);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int removeById(String id){
        Set<String> set = new HashSet<>(1);
        set.add(id);
        return this.removeByIds(set);
    }

    /*
    private void delCaches(String id) {
        redisUtils.delByKey(CACHE_KEY + "::id:", id);
    }

    private void delCaches(Set<String> ids) {
        for (String id: ids) {
            delCaches(id);
        }
    }*/

    /*
    @Override
    public void download(List<DeviceAssignedDto> all, HttpServletResponse response) throws IOException {
      List<Map<String, Object>> list = new ArrayList<>();
      for (DeviceAssignedDto deviceAssigned : all) {
        Map<String,Object> map = new LinkedHashMap<>();
              map.put("设备编码", deviceAssigned.getDeviceCode());
              map.put("指令终点", deviceAssigned.getInstNextdeviceCode());
              map.put("任务终点", deviceAssigned.getTaskNextdeviceCode());
              map.put("参数", deviceAssigned.getParam());
              map.put("备注", deviceAssigned.getRemark());
              map.put("是否启用", deviceAssigned.getIsActive());
              map.put("是否删除", deviceAssigned.getIsDelete());
              map.put("创建者", deviceAssigned.getCreateBy());
              map.put("创建时间", deviceAssigned.getCreateTime());
              map.put("修改者", deviceAssigned.getUpdateBy());
              map.put("修改时间", deviceAssigned.getUpdateTime());
        list.add(map);
      }
      FileUtil.downloadExcel(list, response);
    }*/

    @Override
    public Map<String, Object> queryAll(Map whereJson, Pageable page) {
        IPage<DeviceAssigned> queryPage = PageUtil.toMybatisPage(page);
        LambdaQueryWrapper<DeviceAssigned> wrapper = new LambdaQueryWrapper<>();
        wrapper.orderByDesc(DeviceAssigned::getUpdate_time);
        IPage<DeviceAssigned> deviceAssignedIPage = deviceAssignedMapper.selectPage(queryPage,wrapper);
        final JSONObject json = (JSONObject) JSON.toJSON(ConvertUtil.convertPage(deviceAssignedIPage, DeviceAssigned.class));
        return json;
    }

    @Override
    public List<DeviceAssignedDto> queryAll(Map whereJson) {
        List<DeviceAssigned>  list= new LambdaQueryChainWrapper<>(deviceAssignedMapper)
                .list();
        return ConvertUtil.convertList(list, DeviceAssignedDto.class);
    }

//    @Override
//    public DeviceAssignedDto findById(String assigned_id) {
//        WQLObject wo = WQLObject.getWQLObject("acs_device_assigned");
//        JSONObject json = wo.query("assigned_id ='" + assigned_id + "'").uniqueResult(0);
//        final DeviceAssignedDto obj = json.toJavaObject(DeviceAssignedDto.class);
//        return obj;
//    }

//    @Override
//    public DeviceAssignedDto findByCode(String code) {
//        WQLObject wo = WQLObject.getWQLObject("acs_device_assigned");
//        JSONObject json = wo.query("code ='" + code + "'").uniqueResult(0);
//        final DeviceAssignedDto obj = json.toJavaObject(DeviceAssignedDto.class);
//        return obj;
//    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void create(Map whereJson) {
        JSONObject param = new JSONObject();
        String currentUsername = SecurityUtils.getCurrentUsername();
        String device_code = whereJson.get("device_code").toString();
        String task_nextdevice = String.join(",", (List) whereJson.get("task_nextdevice_code"));
        String inst_nextdevice = String.join(",", (List) whereJson.get("inst_nextdevice_code"));
        ArrayList list = (ArrayList) whereJson.get("tableData");
        JSONObject jo = new JSONObject();
        for (int i = 0; i < list.size(); i++) {
            Map one = (Map) list.get(i);
            String device = one.get("device").toString();
            String limit = one.get("limit").toString();
            String scale = one.get("scale").toString();
            JSONObject data = new JSONObject();
            data.put("limit", limit);
            data.put("scale", scale);
            jo.put(device, data);
        }
        String now = DateUtil.now();
        param.put("assigned_id", IdUtil.simpleUUID());
        param.put("device_code", device_code);
        param.put("task_nextdevice_code", task_nextdevice.toString());
        param.put("inst_nextdevice_code", inst_nextdevice.toString());
        param.put("param", jo);
        param.put("is_active", "1");
        param.put("is_delete", "1");
        param.put("create_by", currentUsername);
        param.put("create_time", now);
        param.put("update_by", currentUsername);
        param.put("update_time", now);
        DeviceAssigned entity = ConvertUtil.convert(param, DeviceAssigned.class);
        deviceAssignedMapper.insert(entity);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(Map whereJson) {
        JSONObject param = new JSONObject();
        String device_code = whereJson.get("device_code").toString();
        String task_nextdevice = String.join(",", (List<String>) whereJson.get("task_nextdevice_code"));
        String inst_nextdevice = String.join(",", (List<String>) whereJson.get("inst_nextdevice_code"));
        String assgined_id = whereJson.get("assigned_id").toString();
        param.put("device_code", device_code);
        param.put("task_nextdevice_code", task_nextdevice.toString());
        param.put("inst_nextdevice_code", inst_nextdevice.toString());
        ArrayList list = (ArrayList) whereJson.get("tableData");
        JSONObject jo = new JSONObject();
        for (int i = 0; i < list.size(); i++) {
            Map one = (Map) list.get(i);
            String device = one.get("device").toString();
            String limit = one.get("limit").toString();
            String scale = one.get("scale").toString();
            JSONObject data = new JSONObject();
            data.put("limit", limit);
            data.put("scale", scale);
            jo.put(device, data);
        }
        param.put("param", jo);
        String currentUsername = SecurityUtils.getCurrentUsername();
        String now = DateUtil.now();
        param.put("update_by", currentUsername);
        param.put("update_time", now);
        DeviceAssigned storageCell = ConvertUtil.convert(param, DeviceAssigned.class);
        deviceAssignedMapper.updateById(storageCell);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteAll(String[] ids) {
        for (String assigned_id : ids) {
            this.removeById(assigned_id);
        }
    }

    @Override
    public void download(List<DeviceAssignedDto> all, HttpServletResponse response) throws IOException {
        List<Map<String, Object>> list = new ArrayList<>();
        for (DeviceAssignedDto deviceAssigned : all) {
            Map<String, Object> map = new LinkedHashMap<>();
            map.put("设备编码", deviceAssigned.getDevice_code());
            map.put("指令终点", deviceAssigned.getInst_nextdevice_code());
            map.put("任务终点", deviceAssigned.getTask_nextdevice_code());
            map.put("参数", deviceAssigned.getParam());
            map.put("备注", deviceAssigned.getRemark());
            map.put("是否启用", deviceAssigned.getIs_active());
            map.put("是否删除", deviceAssigned.getIs_delete());
            map.put("创建者", deviceAssigned.getCreate_by());
            map.put("创建时间", deviceAssigned.getCreate_time());
            map.put("修改者", deviceAssigned.getUpdate_by());
            map.put("修改时间", deviceAssigned.getUpdate_time());
            list.add(map);
        }
        FileUtil.downloadExcel(list, response);
    }

    @Override
    public List<DeviceAssignedDto> queryAssignedBydevice(String device_code, String task_nextdeice_code) {
//        WQLObject wo = WQLObject.getWQLObject("acs_device_assigned");
//        JSONArray arr = wo.query("device_code ='" + device_code + "' and task_nextDevice_code= '" + task_nextdeice_code + "'").getResultJSONArray(0);
//        List<DeviceAssignedDto> list = new ArrayList();
//        for (int i = 0; i < arr.size(); i++) {
//            JSONObject jo = arr.getJSONObject(i);
//            DeviceAssignedDto dto = new DeviceAssignedDto();
//            dto.setAssigned_id(jo.getString("assigned_id"));
//            dto.setDevice_code(jo.getString("device_code"));
//            dto.setInst_nextdevice_code(jo.getString("inst_nextdevice_code"));
//            dto.setTask_nextdevice_code(jo.getString("task_nextdevice_code"));
//            dto.setParam(jo.getString("param"));
//            list.add(dto);
//        }
//        return list;

        List<DeviceAssigned>  list= new LambdaQueryChainWrapper<>(deviceAssignedMapper)
                .eq(DeviceAssigned::getDevice_code,device_code)
                .eq(DeviceAssigned::getTask_nextDevice_code,task_nextdeice_code)
                .list();
        return ConvertUtil.convertList(list, DeviceAssignedDto.class);
    }
}
