package com.hw.tdengine.controller;

import com.hw.common.core.domain.R;
import com.hw.common.core.validated.tdengine.AddTdSTableColumn;
import com.hw.common.core.validated.tdengine.InsertTdTable;
import com.hw.common.security.annotation.InnerAuth;
import com.hw.tdengine.api.domain.*;
import com.hw.tdengine.api.domain.ems.TdSuperTableEmsSelectVo;
import com.hw.tdengine.service.IDeviceStatusService;
import com.hw.tdengine.service.ITdEngineService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.UncategorizedSQLException;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

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

/**
 * @ClassDescription: TdEngine Controller
 * @ClassName: TdEngineController
 * @Author: xins
 * @Date: 2023-08-25 16:38:44
 * @Version 1.0
 */
@RestController
@RequestMapping("/tdengine")
public class TdEngineController {

    @Autowired
    private ITdEngineService tdEngineService;

    @Autowired
    private IDeviceStatusService deviceStatusService;

    private static final Logger log = LoggerFactory.getLogger(TdEngineController.class);

    /* @description 创建数据库
     * @author xins
     * @date 2023-08-28 11:38
     * @param databaseName
     * @return R<?>
     */
    @InnerAuth
    @PostMapping("/createDatabase")
    public R<?> createDataBase(@RequestBody() String databaseName) {
        try {
            //调用创建数据库方法
            this.tdEngineService.createDatabase(databaseName);
            log.info("successfully created database " + databaseName);
            return R.ok("successfully created database " + databaseName);
        } catch (UncategorizedSQLException e) {
            String message = e.getCause().getMessage();
            try {
                message = message.substring(message.lastIndexOf("invalid operation"));
            } catch (Exception ex) {
            }
            log.error(message);
            return R.fail(message);
        } catch (Exception e) {
            log.error(e.getMessage());
            return R.fail(e.getMessage());
        }
    }

    /* * @description：创建超级表
     * @author xins
     * @date 2023-08-28 11:41
     * @param tdSuperTableVo
     * @return R<?>
     */
    @InnerAuth
    @PostMapping("/createSuperTable")
    public R<?> createSuperTable(@Validated @RequestBody TdSuperTableVo tdSuperTableVo) {
        //数据库名称
        String databaseName = tdSuperTableVo.getDatabaseName();
        //超级表名称
        String superTableName = tdSuperTableVo.getSuperTableName();
        //第一个字段名称
        String firstFieldName = tdSuperTableVo.getFirstFieldName();
        //schema列字段（超级表结构）对象集合
        List<TdField> schemaFields = tdSuperTableVo.getSchemaFields();
        //标签字段对象集合
        List<TdField> tagsFields = tdSuperTableVo.getTagsFields();

        try {
            //将Schema字段对象和标签字段对象转换为创建表的字段Vo类对象集合
            List<TdFieldVo> schemaFieldsVos = TdFieldVo.batchConvertFields(schemaFields);
            List<TdFieldVo> tagsFieldsVos = TdFieldVo.batchConvertFields(tagsFields);
            this.tdEngineService.createSuperTable(databaseName, superTableName, firstFieldName, schemaFieldsVos, tagsFieldsVos);
            log.info("successfully created superTable " + superTableName);
            return R.ok("successfully created superTable " + superTableName);
        } catch (UncategorizedSQLException e) {
            String message = e.getCause().getMessage();
            try {
                message = message.substring(message.lastIndexOf("invalid operation"));
            } catch (Exception ex) {
            }
            log.error(message);
            return R.fail(message);
        } catch (Exception e) {
            log.error(e.getMessage());
            return R.fail(e.getMessage());
        }
    }

    /**
     * @return R<?>
     * @param: tableDto
     * @description 创建子表
     * @author xins
     * @date 2023-08-28 16:17
     */
    @InnerAuth
    @PostMapping("/createTable")
    public R<?> createTable(@Validated @RequestBody TdTableVo tdTableVo) {
        try {
            String databaseName = tdTableVo.getDatabaseName();
            String superTableName = tdTableVo.getSuperTableName();
            String tableName = tdTableVo.getTableName();
            List<TdField> tagsFieldValues = tdTableVo.getTagsFieldValues();
            this.tdEngineService.createTable(databaseName, superTableName, tableName, tagsFieldValues);
            log.info("successfully created table " + tableName);
            return R.ok("successfully created table " + tableName);
        } catch (Exception e) {
            String message = e.getCause().getMessage();
            try {
                message = message.substring(message.lastIndexOf("invalid operation"));
            } catch (Exception ex) {
                log.error(ex.getMessage());
            }
            log.error(message);
            return R.fail(message);
        }
    }


    /**
     * @return R<?>
     * @param: tdSuperTableVo
     * @description 超级表增加列
     * @author xins
     * @date 2023-08-28 17:55
     */
    @InnerAuth
    @PostMapping("/addSuperTableColumn")
    public R<?> addSuperTableColumn(@Validated(AddTdSTableColumn.class) @RequestBody TdSuperTableVo tdSuperTableVo) {
        String databaseName = tdSuperTableVo.getDatabaseName();
        String superTableName = tdSuperTableVo.getSuperTableName();
        TdField addTdField = tdSuperTableVo.getField();
        try {
            TdFieldVo addFieldVo = TdFieldVo.convertField(addTdField);
            this.tdEngineService.addSuperTableColumn(databaseName, superTableName, addFieldVo);
            log.info("successfully added column for superTable " + superTableName);
            return R.ok("successfully added column for superTable " + superTableName);
        } catch (UncategorizedSQLException e) {
            String message = e.getCause().getMessage();
            try {
                message = message.substring(message.lastIndexOf("invalid operation"));
            } catch (Exception ex) {
            }
            log.error(message);
            return R.fail(message);
        } catch (Exception e) {
            log.error(e.getMessage());
            return R.fail(e.getMessage());
        }
    }

    /**
     * @return R<?>
     * @param: tdSuperTableVo
     * @description 超级表增加列
     * @author xins
     * @date 2023-08-28 17:55
     */
    @InnerAuth
    @PostMapping("/modifySuperTableColumn")
    public R<?> modifySuperTableColumn(@Validated(AddTdSTableColumn.class) @RequestBody TdSuperTableVo tdSuperTableVo) {
        String databaseName = tdSuperTableVo.getDatabaseName();
        String superTableName = tdSuperTableVo.getSuperTableName();
        TdField modifyTdField = tdSuperTableVo.getField();
        try {
            TdFieldVo modifyTdFieldVo = TdFieldVo.convertField(modifyTdField);
            this.tdEngineService.modifySuperTableColumn(databaseName, superTableName, modifyTdFieldVo);
            log.info("successfully modified column for superTable {} ", superTableName);
            return R.ok("successfully modified column for superTable " + superTableName);
        } catch (UncategorizedSQLException e) {
            String message = e.getCause().getMessage();
            try {
                message = message.substring(message.lastIndexOf("invalid operation"));
            } catch (Exception ex) {
            }
            log.error(message);
            return R.fail(message);
        } catch (Exception e) {
            log.error(e.getMessage());
            return R.fail(e.getMessage());
        }
    }


    /**
     * @return R<?>
     * @param: tdSuperTableVo
     * @description 超级表删除列
     * @author xins
     * @date 2023-08-28 17:56
     */
    @InnerAuth
    @PostMapping("/dropSuperTableColumn")
    public R<?> dropColumnForSuperTable(@Validated(AddTdSTableColumn.class) @RequestBody TdSuperTableVo tdSuperTableVo) {
        String databaseName = tdSuperTableVo.getDatabaseName();
        String superTableName = tdSuperTableVo.getSuperTableName();
        TdField dropField = tdSuperTableVo.getField();

        try {
//            TdFieldVo dropFieldVo = TdFieldVo.convertField(dropField);
            this.tdEngineService.dropSuperTableColumn(databaseName, superTableName, dropField);
            log.info("successfully droped column of superTable " + superTableName);
            return R.ok("successfully droped column of superTable " + superTableName);
        } catch (UncategorizedSQLException e) {
            String message = e.getCause().getMessage();
            try {
                message = message.substring(message.lastIndexOf("invalid operation"));
            } catch (Exception ex) {
            }
            log.error(message);
            return R.fail(message);
        } catch (Exception e) {
            log.error(e.getMessage());
            return R.fail(e.getMessage());
        }
    }

    /**
     * @return R<?>
     * @param: alterTagVo
     * @description 修改子表tag值
     * @author xins
     * @date 2023-08-30 11:17
     */
    @InnerAuth
    @PostMapping("/alterTableTag")
    public R<?> alterTableTag(@Validated @RequestBody AlterTagVo alterTagVo) {
        String databaseName = alterTagVo.getDatabaseName();
        String tableName = alterTagVo.getTableName();
        String tagName = alterTagVo.getTagName();
        Object tagValue = alterTagVo.getTagValue();

        try {
            this.tdEngineService.alterTableTag(databaseName, tableName, tagName, tagValue);
            log.info("successfully altered tag " + tagName + " value to " + tagValue + " of tableName");
            return R.ok("successfully altered tag " + tagName + " value to " + tagValue + " of tableName");
        } catch (UncategorizedSQLException e) {
            String message = e.getCause().getMessage();
            try {
                message = message.substring(message.lastIndexOf("invalid operation"));
            } catch (Exception ex) {
            }
            log.error(message);
            return R.fail(message);
        } catch (Exception e) {
            log.error(e.getMessage());
            return R.fail(e.getMessage());
        }
    }

    /**
     * @return R<?>
     * @param: tdTableVo
     * @description 插入数据
     * @author xins
     * @date 2023-08-29 10:04
     */
    @InnerAuth
    @PostMapping("/insertTable")
    public R<?> insertTable(@Validated(InsertTdTable.class) @RequestBody TdTableVo tdTableVo) {
        try {
            String databaseName = tdTableVo.getDatabaseName();
            String tableName = tdTableVo.getTableName();
            List<TdField> schemaFields = tdTableVo.getSchemaFields();

            this.tdEngineService.insertTable(databaseName, tableName, schemaFields);
            log.info("success for insert table " + databaseName + "." + tableName);
            return R.ok();
        } catch (UncategorizedSQLException e) {
            String message = e.getCause().getMessage();
            try {
                message = message.substring(message.lastIndexOf("invalid operation"));
            } catch (Exception ex) {
            }
            log.error(message);
            return R.fail(message);
        } catch (Exception e) {
            log.error(e.getMessage());
            return R.fail(e.getMessage());
        }
    }

    /**
     * @return R<?>
     * @param: tdSelectDto
     * @description 获取某个子表最新一条数据
     * @author xins
     * @date 2023-08-29 11:26
     */
    @InnerAuth
    @PostMapping("/getLatestData")
    public R<?> getLatestData(@Validated @RequestBody TdSelectDto tdSelectDto) {
        try {
            return R.ok(this.tdEngineService.getLatestData(tdSelectDto));
        } catch (UncategorizedSQLException e) {
            String message = e.getCause().getMessage();
            try {
                message = message.substring(message.lastIndexOf("invalid operation"));
            } catch (Exception ex) {
            }
            log.error(message);
            return R.fail(message);
        } catch (Exception e) {
            log.error(e.getMessage());
            return R.fail(e.getMessage());
        }
    }

    /**
     * @return R<Map < String, Map < String, Object>>>
     * @param: tdSelectDto
     * @description 根据tagsname获取超级表最新信息
     * @author xins
     * @date 2023-08-29 14:51
     */
    @InnerAuth
    @PostMapping("/getLatestDataByTags")
    public R<List<Map<String, Object>>> getLatestDataByTags(@Validated @RequestBody TdSuperTableSelectVo tdSelectDto) {
        try {
            return R.ok(this.tdEngineService.getLatestDataByTags(tdSelectDto));
        } catch (UncategorizedSQLException e) {
            String message = e.getCause().getMessage();
            try {
                message = message.substring(message.lastIndexOf("invalid operation"));
            } catch (Exception ex) {
            }
            log.error(message);
            return R.fail(message);
        } catch (Exception e) {
            log.error(e.getMessage());
            return R.fail(e.getMessage());
        }
    }


    /**
     * @param tdHistorySelectDto
     * @return R<?>
     * @MethodDescription 可视化数据  返回格式，时间，数值列
     * 历史数据 SELECT voltage ,ts FROM test.meters where ts between '2017-07-14 02:40:00.000' and '2017-07-14 02:40:00.001' LIMIT [topnums]
     * ts > now - 24h;
     * 实时数据 select col from table LIMIT [topnums]
     * 聚合数据 select [avg/max/sum/count..](col) from table where ts between '2017-07-14 02:40:00.000' and '2017-07-14 02:40:00.001' group by col LIMIT [topnums]
     */
    @InnerAuth
    @PostMapping("/getHistoryData")
    public R<?> getHistoryData(@Validated @RequestBody TdHistorySelectDto tdHistorySelectDto) {
        try {
//            if (selectVisualDto.getType() == 0) {//查询历史
//                return R.ok(this.tdEngineService.getHistoryData(selectVisualDto));
//            }else if(selectVisualDto.getType() == 1) {//查询实时
//                return R.ok(this.tdEngineService.getRealtimeData(selectVisualDto));
//            }else {//查询聚合
//                return R.ok(this.tdEngineService.getAggregateData(selectVisualDto));
//            }
            int count = this.tdEngineService.getCountOfHistoryData(tdHistorySelectDto);
            TdReturnDataVo returnDataVo = new TdReturnDataVo();
            returnDataVo.setCount(count);
            returnDataVo.setDataList(this.tdEngineService.getHistoryData(tdHistorySelectDto));
            return R.ok(returnDataVo);
        } catch (UncategorizedSQLException e) {
            String message = e.getCause().getMessage();
            try {
                message = message.substring(message.lastIndexOf("invalid operation"));
            } catch (Exception ex) {
            }
            log.error(message);
            return R.fail(message);
        } catch (Exception e) {
            log.error(e.getMessage());
            return R.fail(e.getMessage());
        }
    }


    @InnerAuth
    @PostMapping("/getSuperTableHistoryData")
    public R<TdReturnDataVo> getSuperTableHistoryData(@Validated @RequestBody TdSuperTableEmsSelectVo tdSuperTableEmsSelectVo) {
        try {
            int count = this.tdEngineService.getCountOfSuperTableHistoryData(tdSuperTableEmsSelectVo);
            TdReturnDataVo returnDataVo = new TdReturnDataVo();
            returnDataVo.setCount(count);
            returnDataVo.setDataList(this.tdEngineService.getSuperTableHistoryData(tdSuperTableEmsSelectVo));
            return R.ok(returnDataVo);
        } catch (UncategorizedSQLException e) {
            String message = e.getCause().getMessage();
            try {
                message = message.substring(message.lastIndexOf("invalid operation"));
            } catch (Exception ex) {
            }
            log.error(message);
            return R.fail(message);
        } catch (Exception e) {
            log.error(e.getMessage());
            return R.fail(e.getMessage());
        }
    }


    /**
     * @return R<?>
     * @param: queryDeviceStatus
     * @description 获取每天在线设备信息
     * @author xins
     * @date 2023-08-29 11:26
     */
    @InnerAuth
    @PostMapping("/getOnlineDevicesGroupByDay")
    public R<?> getOnlineDevicesGroupByDay(@RequestBody DeviceStatus queryDeviceStatus) {
        try {
            List<DeviceStatus> deviceStatuses = this.deviceStatusService.getOnlineDevicesGroupByDay(queryDeviceStatus);
            Map<Long, List<DeviceStatus>> deviceStatusMap = deviceStatuses.stream()
                    .collect(Collectors.groupingBy(DeviceStatus::getDeviceId));
            return R.ok(deviceStatusMap);
        } catch (UncategorizedSQLException e) {
            String message = e.getCause().getMessage();
            try {
                message = message.substring(message.lastIndexOf("invalid operation"));
            } catch (Exception ex) {
            }
            log.error(message);
            return R.fail(message);
        } catch (Exception e) {
            log.error(e.getMessage());
            return R.fail(e.getMessage());
        }
    }


    /**
     * @return R<?>
     * @param: queryDeviceStatus
     * @description 获取最近一次在线设备信息
     * @author xins
     * @date 2023-08-29 11:26
     */
    @InnerAuth
    @PostMapping("/getLastOnlineDevices")
    public R<?> getLastOnlineDevices(@RequestBody DeviceStatus queryDeviceStatus) {
        try {
            List<Map<String, Object>> deviceStatusMapList = this.deviceStatusService.getLastOnlineDevices(queryDeviceStatus);
            return R.ok(deviceStatusMapList);
        } catch (UncategorizedSQLException e) {
            String message = e.getCause().getMessage();
            try {
                message = message.substring(message.lastIndexOf("invalid operation"));
            } catch (Exception ex) {
            }
            log.error(message);
            return R.fail(message);
        } catch (Exception e) {
            log.error(e.getMessage());
            return R.fail(e.getMessage());
        }
    }


    /**
     * @return R<?>
     * @param: tdSelectDto
     * @description 获取最近一次在线设备信息
     * @author xins
     * @date 2023-08-29 11:26
     */
    @InnerAuth
    @PostMapping("/getDeviceStatusList")
    public R<List<Map<String, Object>>> getDeviceStatusList(@RequestBody DeviceStatus queryDeviceStatus) {
        try {
            List<Map<String, Object>> deviceStatusMapList = this.deviceStatusService.getDeviceStatusList(queryDeviceStatus);
            return R.ok(deviceStatusMapList);
        } catch (UncategorizedSQLException e) {
            String message = e.getCause().getMessage();
            try {
                message = message.substring(message.lastIndexOf("invalid operation"));
            } catch (Exception ex) {
            }
            log.error(message);
            return R.fail(message);
        } catch (Exception e) {
            log.error(e.getMessage());
            return R.fail(e.getMessage());
        }
    }



    /**
     * @return R<?>
     * @param: alterTagVos
     * @description 批量修改子表tag值
     * @author xins
     * @date 2023-08-30 11:17
     */
    @InnerAuth
    @PostMapping("/alterTableTags")
    public R<?> alterTableTags(@Validated @RequestBody List<AlterTagVo> alterTagVos) {

        try {
            this.tdEngineService.alterTableTags(alterTagVos);
            log.info("successfully altered tag " + alterTagVos.toString());
            return R.ok("successfully altered tag " + alterTagVos.toString());
        } catch (UncategorizedSQLException e) {
            String message = e.getCause().getMessage();
            try {
                message = message.substring(message.lastIndexOf("invalid operation"));
            } catch (Exception ex) {
            }
            log.error(message);
            return R.fail(message);
        } catch (Exception e) {
            log.error(e.getMessage());
            return R.fail(e.getMessage());
        }
    }


}
