package org.dromara.controller;

import java.util.*;

import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import lombok.RequiredArgsConstructor;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.*;
import cn.dev33.satoken.annotation.SaCheckPermission;
import org.dromara.domain.TblBreakdown;
import org.dromara.domain.bo.TblBreakdownBo;
import org.dromara.domain.vo.TblBreakdownVo;
import org.dromara.service.ITblBreakdownService;
import org.dromara.system.domain.SysDept;
import org.dromara.system.domain.bo.SysDeptBo;
import org.dromara.system.domain.bo.SysDictDataBo;
import org.dromara.system.domain.vo.SysDeptVo;
import org.dromara.system.domain.vo.SysDictDataVo;
import org.dromara.system.service.ISysDeptService;
import org.dromara.system.service.ISysDictDataService;
import org.springframework.web.bind.annotation.*;
import org.springframework.validation.annotation.Validated;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
import org.dromara.common.log.annotation.Log;
import org.dromara.common.web.core.BaseController;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.excel.utils.ExcelUtil;
import org.dromara.domain.vo.TblSensorVo;
import org.dromara.domain.bo.TblSensorBo;
import org.dromara.service.ITblSensorService;
import org.dromara.common.mybatis.core.page.TableDataInfo;

/**
 * 传感器列
 *
 * @author Lion Li
 * @date 2024-08-11
 */
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/system/sensor")
public class TblSensorController extends BaseController {

    private final ITblSensorService tblSensorService;

    private final ISysDeptService sysDeptService;

    private final ISysDictDataService sysDictDataService;

    private final ITblBreakdownService breakdownService;

    /**
     * 查询传感器列列表
     */
    @GetMapping("/list")
    public TableDataInfo<TblSensorVo> list(TblSensorBo bo, PageQuery pageQuery) {
        return tblSensorService.queryPageList(bo, pageQuery);
    }

    @GetMapping("/faultTop")
    public R<List<TblSensorVo>> faultTop() {

        List<TblBreakdownVo> breakdownVos = breakdownService.queryList(new TblBreakdownBo());
        Map<Long,Integer> sendMap = new HashMap<>();
        breakdownVos.forEach(item->{
            if(sendMap.get(item.getSensorId())==null){
                sendMap.put(item.getSensorId(),0);
            }
            sendMap.put(item.getSensorId(),sendMap.get(item.getSensorId())+1);
        });
        List<TblSensorVo> sensorVos =  tblSensorService.queryList(new TblSensorBo());
        sensorVos.forEach(item->{
            if(sendMap.get(item.getId())!=null){
                item.setFaultCount(sendMap.get(item.getId())==null?0:sendMap.get(item.getId()));
            }
        });
//        sensorVos.sort(Comparator.comparing(TblSensorVo::getFaultCount).reversed());

        return R.ok(sensorVos);
    }

    @GetMapping("/listTree")
    public R listTree(TblSensorBo bo) {
        List<TblSensorVo> list =  tblSensorService.queryList(bo);
        Map<String,Map<String,List<TblSensorVo>>> map = new HashMap<>();
        Map<Long,SysDeptVo> mapD = new HashMap<>();
        Map<String,String> mapdic = new HashMap<>();


        List<SysDeptVo> depts = sysDeptService.selectDeptList(new SysDeptBo());
        depts.forEach(item->{
            mapD.put(item.getDeptId(),item);
        });
        SysDictDataBo bod = new SysDictDataBo();
        bod.setDictType("sensor_type");
        List<SysDictDataVo> dictList = sysDictDataService.selectDictDataList(bod);
        dictList.forEach(item->{
            mapdic.put(item.getDictValue(),item.getDictLabel());
        });

        List<String> deptids = new ArrayList<>();

        //部门-摄像机-[a]
        list.forEach(item->{
            SysDeptVo d =  mapD.get(item.getCreateDept());
            for (String tt : d.getAncestors().split(",")) {
                if(!deptids.contains(tt)){
                    deptids.add(tt);
                }
            }
            if(!deptids.contains(d.getDeptId().toString())){
                deptids.add(d.getDeptId().toString());
            }

            String deptname =  mapD.get(item.getCreateDept()).getDeptId().toString();
            if(map.get(deptname)==null) map.put(deptname,new HashMap<>());
            if(map.get(deptname).get(mapdic.get(item.getSensorType()))==null) map.get(deptname).put(mapdic.get(item.getSensorType()),new ArrayList<>());
            map.get(deptname).get(mapdic.get(item.getSensorType())).add(item);
        });

        //过滤
        SysDeptBo depb = new SysDeptBo();
        depb.getParams().put("depts",deptids);
        List<Tree<Long>> depttree = sysDeptService.selectDeptTreeList(depb);

        //宁夏-固原-摄像机-[a]

        depttree.forEach(item->{
            buildDeviceTree(map,item);

        });





        return R.ok(depttree);

    }

    private void buildDeviceTree(Map<String,Map<String,List<TblSensorVo>>> mapd,Tree data){
        data.put("value",data.get("label"));
        if(mapd.get(data.get("id").toString())!=null){
            if(data.getChildren()==null){
                data.setChildren(new ArrayList<>());
            }
            List<Object> objects =new ArrayList<>();
            mapd.get(data.get("id").toString()).forEach((k1,v1)->{
                Map<String,Object> d1 = new HashMap<>();
                d1.put("label",k1);
                d1.put("value",k1);
                List<Object> objects1 =new ArrayList<>();
                v1.forEach(item1->{
                    Map<String,Object> d2 = new HashMap<>();
                    d2.put("label",item1.getName()+ StrUtil.format("[{}]", JSONUtil.parseObj(item1.getExt1()).getStr("ip")));
                    d2.put("value",item1.getId());
                    objects1.add(d2);
                });
                d1.put("children",objects1);
                objects.add(d1);
            });
            data.getChildren().addAll(objects);
        }
        if(data.getChildren()!=null){
            for (Object c : data.getChildren()) {
                if(c instanceof  Tree){
                    buildDeviceTree(mapd,(Tree) c);
                }
            }
        }
    }

    /**
     * 导出传感器列列表
     */
    @Log(title = "传感器列", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(TblSensorBo bo, HttpServletResponse response) {
        List<TblSensorVo> list = tblSensorService.queryList(bo);
        ExcelUtil.exportExcel(list, "传感器列", TblSensorVo.class, response);
    }

    /**
     * 获取传感器列详细信息
     *
     * @param id 主键
     */
    @GetMapping("/{id}")
    public R<TblSensorVo> getInfo(@NotNull(message = "主键不能为空")
                                     @PathVariable Long id) {
        return R.ok(tblSensorService.queryById(id));
    }

    /**
     * 新增传感器列
     */
    @Log(title = "传感器列", businessType = BusinessType.INSERT)
    @RepeatSubmit()
    @PostMapping()
    public R<Void> add(@Validated(AddGroup.class) @RequestBody TblSensorBo bo) {
        return toAjax(tblSensorService.insertByBo(bo));
    }

    /**
     * 修改传感器列
     */
    @Log(title = "传感器列", businessType = BusinessType.UPDATE)
    @RepeatSubmit()
    @PutMapping()
    public R<Void> edit(@Validated(EditGroup.class) @RequestBody TblSensorBo bo) {
        return toAjax(tblSensorService.updateByBo(bo));
    }

    /**
     * 删除传感器列
     *
     * @param ids 主键串
     */
    @Log(title = "传感器列", businessType = BusinessType.DELETE)
    @DeleteMapping("/{ids}")
    public R<Void> remove(@NotEmpty(message = "主键不能为空")
                          @PathVariable Long[] ids) {
        return toAjax(tblSensorService.deleteWithValidByIds(List.of(ids), true));
    }

    @PutMapping("/{id}/{name}")
    public R<Object> sencmd(@NotNull(message = "主键不能为空")
                                  @PathVariable Long id,@PathVariable String name) {
        //TODO 发送指令
        System.out.println(id);
        System.out.println(name);
        return R.ok();
    }
}
