package com.zcxk.controller;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zcxk.client.UserCenterClient;
import com.zcxk.common.FileUploadUtil;
import com.zcxk.entity.*;
import com.zcxk.model.AjaxMessage;
import com.zcxk.model.LoginUser;
import com.zcxk.model.Pagination;
import com.zcxk.model.ResultStatus;
import com.zcxk.service.ParmSettingService;
import com.zcxk.util.UserUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;

import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.util.*;
import java.util.regex.Pattern;

import org.springframework.web.bind.annotation.*;
import com.zcxk.service.SceneService;
import org.springframework.web.multipart.MultipartFile;

/**
 * 场景信息页面控制器
 * @author WYY
 * @date 2020-11-17 21:15
 */
@RestController
@RequestMapping("/scene")
@Api(tags = "场景管理")
public class SceneController {
    @Autowired
    private SceneService sceneService;
    @Value("${SMS.sys_config_path}")
    private String baseDir;
    @Autowired
    UserCenterClient userCenterClient;
    @Autowired
    private ParmSettingService parmSettingService;

    @ApiOperation(value = "分页查询场景")
    @RequestMapping(value = "/selectPage", method = RequestMethod.GET)
    @ResponseBody
    public AjaxMessage<Pagination<SceneEntity>> selectPage(@RequestParam Integer pageNum, @RequestParam Integer pageSize, @RequestParam(value = "sceneName", required = false) String sceneName,@RequestParam(required = false) Long companyOrgId,@RequestParam(required = false) Long deptOrgId) {
        IPage<SceneEntity> iPage = new Page<>(pageNum, pageSize);
        SceneEntity sceneEntity = new SceneEntity();
        sceneEntity.setSceneName(sceneName);
        sceneEntity.setCompanyOrgId(companyOrgId);
        sceneEntity.setDeptOrgId(deptOrgId);
        iPage = sceneService.findPage(iPage, sceneEntity);
        Pagination<SceneEntity> pages = new Pagination<>(iPage);
        return new AjaxMessage<>(ResultStatus.OK, pages);
    }

    @ApiOperation(value = "查询场景树")
    @RequestMapping(value = "/selectList", method = RequestMethod.POST)
    @ResponseBody
    public AjaxMessage<List<SceneEntity>> allList() {
        SceneEntity sceneEntity = new SceneEntity();
        List<SceneEntity> menuEntities = sceneService.findAllList(sceneEntity);
        return new AjaxMessage<>(ResultStatus.OK, menuEntities);
    }

    @ApiOperation(value = "查询场景树")
    @RequestMapping(value = "/selectListForParm", method = RequestMethod.POST)
    @ResponseBody
    public AjaxMessage<List<SceneEntity>> selectListForParm(@RequestParam(required = false) Long comId,@RequestParam(required = false) Long deptId) {
        if (comId != null) {
            SceneEntity sceneEntity = new SceneEntity();
            sceneEntity.setCompanyOrgId(comId);
            sceneEntity.setDeptOrgId(deptId);
            List<SceneEntity> menuEntities = sceneService.findAllList(sceneEntity);
            return new AjaxMessage<>(ResultStatus.OK, menuEntities);
        } else {
            return new AjaxMessage<>(ResultStatus.OK);
        }
    }



    /**
     * 新增
     */
    @ApiOperation(value = "场景图片")
    @RequestMapping(value = "addSceneImage", method = RequestMethod.POST)
    @ResponseBody
    public AjaxMessage<String> addUserPhoto(@ApiParam(value = "场景图片", required = true) @RequestParam("avatarfile") MultipartFile file) {
        String avatar = "";
        if (!file.isEmpty()) {
            try {
                avatar = FileUploadUtil.uploadWeb(baseDir, file);
            } catch (IOException e) {
                return new AjaxMessage<>(ResultStatus.ERROR, e.getMessage());
            }
        }
        return new AjaxMessage<>(ResultStatus.OK, avatar);
    }

    /**
     * 新增
     */
    @ApiOperation(value = "上传多个场景图片")
    @RequestMapping(value = "addSceneImages", method = RequestMethod.POST)
    @ResponseBody
    public AjaxMessage<String> addUserPhotos(@ApiParam(value = "场景图片", required = true) @RequestParam("avatarfile") MultipartFile[] file) {
        String avatar = "";
        if (file.length > 0) {
            for (MultipartFile item : file) {
                try {
                    avatar += FileUploadUtil.uploadWeb(baseDir, item)+",";
                } catch (IOException e) {
                    return new AjaxMessage<>(ResultStatus.ERROR, e.getMessage());
                }
            }
        }
        return new AjaxMessage<>(ResultStatus.OK, avatar.substring(0,avatar.length()-1));
    }

    /**
     * 新增
     */
    @ApiOperation(value = "新增")
    @RequestMapping(value = "/add", method = RequestMethod.POST)
    @ResponseBody
    public AjaxMessage<Integer> addScene(@ApiParam(value = "场景", required = true) @RequestBody SceneEntity scene) {
        int result = sceneService.addScene(scene) ? 1 : 0;
        return new AjaxMessage<>(ResultStatus.OK, result);
    }


    /**
     * 按ID查询场景
     */
    @ApiOperation(value = "按ID查询场景")
    @RequestMapping(value = "/selectById", method = RequestMethod.GET)
    @ResponseBody
    public AjaxMessage<SceneEntity> selectById(@ApiParam(value = "ID", required = true) @RequestParam Long id) {
        SceneEntity scene = sceneService.findSceneById(id);
        return new AjaxMessage<>(ResultStatus.OK, scene);
    }

    /**
     * 修改保存场景信息
     */
    @RequestMapping(value = "/edit", method = RequestMethod.POST)
    @ResponseBody
    @ApiOperation(value = "修改保存场景信息")
    public AjaxMessage<Integer> editScene(@ApiParam(value = "场景", required = true) @RequestBody SceneEntity scene) {

        //SceneEntity cScene = sceneService.findSceneById(scene.getId());
        if(scene.getParentSceneId()!=null&&scene.getParentSceneId().equals(scene.getId()))
        {
            return new AjaxMessage<>(ResultStatus.SCENE_PARENT_ALREADY_EXISTS);
        }
        int result = sceneService.updateSceneById(scene) ? 1 : 0;
        return new AjaxMessage<>(ResultStatus.OK, result);
    }
    @RequestMapping(value = "/findByParentIdsLike", method = RequestMethod.GET)
    @ResponseBody
    @ApiOperation(value = "根据父级ID查询所有子节点及本身")
    public  List<Long> findByParentIdsLike(@ApiParam(value = "父级场景ID", required = false)@RequestParam(required = false) Long id) {
        List<Long> longs = sceneService.findByParentIdsLike(id);
        return longs;
    }
    /**
     * 删除
     */
    @ApiOperation(value = "删除")
    @RequestMapping(value = "/deleteByIds", method = RequestMethod.POST)
    @ResponseBody
    public AjaxMessage<Integer> del(@ApiParam(value = "场景ID", required = true) @RequestBody Long[] ids) {

        List<SceneEntity> scenes = sceneService.findByParentSceneIds(ids);
        if (scenes.size() > 0) {
            return new AjaxMessage<>(ResultStatus.EXSIT_IS_PARENT_ERROR);
        }
        int result = sceneService.delSceneByIds(ids) ? 1 : 0;
        return new AjaxMessage<>(ResultStatus.OK, result);
    }
    /**
     * 一级场景查询
     */
    @ApiOperation(value = "一级场景查询",notes = "sceneTypeName 为水源、水厂、泵站")
    @RequestMapping(value = "/selectByTypeName", method = RequestMethod.GET)
    @ResponseBody
    public AjaxMessage< List<SceneEntity>> selectByTypeName(@ApiParam(value = "一级场景类型名称", required = true) @RequestParam String sceneTypeName) {
        SceneEntity sceneEntity = new SceneEntity();
        sceneEntity.setSceneTypeName(sceneTypeName);
        List<SceneEntity> sceneEntities = sceneService.selectByTypeName(sceneEntity);
        return new AjaxMessage<>(ResultStatus.OK, sceneEntities);
    }
    @RequestMapping(value = "/findByParentId", method = RequestMethod.GET)
    @ResponseBody
    @ApiOperation(value = "根据父级ID查询所有子节点及本身(全部信息)")
    public  AjaxMessage<List<SceneEntity>> findByParentId(@ApiParam(value = "父级场景ID", required = false)@RequestParam(required = false) Long id) {
        List<SceneEntity> sceneEntities = sceneService.findByParentId(id);
        return new AjaxMessage<>(ResultStatus.OK, sceneEntities);
    }

    @RequestMapping(value="batchSave" , method = RequestMethod.POST)
    @ApiOperation(value = "批量绑定设备及参数(绑定设备)")
    public AjaxMessage<Integer> batchEdit( @ApiParam(value = "设备信息") @RequestBody List<DeviceSceneEntity> deviceScenes){
        sceneService.saveUpdateBatch(deviceScenes);
        return new AjaxMessage<>(ResultStatus.OK,1 );
    }

    @RequestMapping(value = "/selectAlarmSceneAndDevice", method = RequestMethod.GET)
    @ResponseBody
    @ApiOperation(value = "场景及设备故障率")
    public  AjaxMessage<Object> selectAlarmSceneAndDevice(
            @ApiParam(value = "统计类型:0-按月统计,1-按年统计,2-自定义统计", required = true) @RequestParam(required = true) int statsType,
            @ApiParam(value = "统计时间:月格式(yyyy-MM),年格式(yyyy),自定义统计时间开始日期", required = true) @RequestParam(required = true) String startDate,
            @ApiParam(value = "统计时间:年月统计不用传入此参数,自定义统计截至日期", required = false) @RequestParam(required = false) String endDate) throws ParseException {
        LocalDate localDate = LocalDate.now();
        LoginUser loginUser = UserUtil.getCurrentUser();
        SceneEntity sceneEntity = new SceneEntity();
        sceneEntity.setTenantId(loginUser.getTenantId());
        sceneEntity.setProgramItems(loginUser.getProgramItemList());
        sceneEntity.setUserType(loginUser.getType());
        //1是公司，2是公司及以下，3部门，4部门及以下，5自定义
        sceneEntity.setPermissonType(loginUser.getPermissonType());
        int days = 1;
        switch (statsType) {
            case 0:
                startDate = String.format("%s-01", startDate);
                endDate = subMonth(startDate, 1);
                days =getDaysOfMonth(startDate);
                if(localDate.getYear() == Integer.parseInt(startDate.substring(0,4))&&
                localDate.getMonthValue() == Integer.parseInt(startDate.substring(5,7))){
                    days = localDate.getDayOfMonth();
                }
                break;
            case 1:
                int year = Integer.parseInt(startDate);
                if(year == localDate.getYear()){
                    days = differentDaysByMillisecond(String.format("%s-%s-%s",startDate,1,1),
                            String.format("%s-%s-%s",localDate.getYear(),localDate.getMonthValue(),localDate.getDayOfMonth()+1));
                }
                else {
                    days = LocalDate.of(year, 1, 1).lengthOfYear();
                }
                startDate = String.format("%s-01-01", startDate);
                endDate = subYear(startDate, 1);
                break;
            case 2:
                startDate = String.format("%s-01", startDate);
                endDate = String.format("%s-01", endDate);
                if(isCurrentMonth(endDate)==true){
                    endDate = String.format("%s-%s", endDate.substring(0,7),localDate.getDayOfMonth()+1);
                }
                else {
                    endDate = subMonth(endDate, 1);
                }
                days = differentDaysByMillisecond(startDate,endDate);
                break;
        }
        ParmSettingEntity parmSettingEntity = new ParmSettingEntity();
        parmSettingEntity.setTenantId(loginUser.getTenantId());
        parmSettingEntity.setCompanyOrgId(Long.valueOf(loginUser.getCompanyId().toString()));
        parmSettingEntity.setParmType(3);
        List<ParmSettingEntity> paramSettingList = parmSettingService.findList(parmSettingEntity);
        if(paramSettingList.size()==0){
            return new AjaxMessage<>(55555,"没有配置故障率参数",null);
        }
        ParmSettingEntity parmSetting = paramSettingList.get(0);
        String paramValue = parmSetting.getParmValue();
        String[] params =  paramValue.split(";");
        if(params.length!=3 ){
           return new AjaxMessage<>(55555,"参数设置格式错误!请参照正确格式设置:0.5;0.5~0.2;0.2",null);
        }
        String[] mParam = params[1].split("~");
        if(mParam.length!=2){
           return new AjaxMessage<>(55555,"参数设置格式错误!请参照正确格式设置:0.5;0.5~0.2;0.2",null);
        }
        if(validateNumber(params[0])==false || validateNumber(params[2])==false
                || validateNumber(mParam[0])==false || validateNumber(mParam[1])==false){
            return new AjaxMessage<>(55555,"参数设置格式错误!请参照正确格式设置:0.5;0.5~0.2;0.2",null);
        }
        List<Map<String,Object>> list = sceneService.selectAlarmSceneAndDevice(sceneEntity, startDate, endDate);
        for(int i=0;i<list.size();i++){
            Map<String,Object> map = list.get(i);
            double amount =Double.parseDouble(map.get("amount").toString());
            double rate =amount / days;
            map.put("rate",rate);

            if(rate>=Double.parseDouble(params[0])){
                map.put("level","高");
            }
            else if(rate>=Double.parseDouble(mParam[1]) && rate<Double.parseDouble(mParam[0])){
                map.put("level","中");
            }
            else if(rate<Double.parseDouble(params[2])){
                map.put("level","低");
            }
        }
        return new AjaxMessage<>(ResultStatus.OK, list);
    }

    @RequestMapping(value = "/alarmTimesStatistics", method = RequestMethod.GET)
    @ResponseBody
    @ApiOperation(value = "报警次数统计")
    public  AjaxMessage<List<Map<String,Object>>> alarmTimesStatistics(
            @ApiParam(value = "设备或场景ID", required = true) @RequestParam(required = true) int id,
            @ApiParam(value = "设备或场景标识(1:设备;2:场景)", required = true) @RequestParam(required = true) int sort,
            @ApiParam(value = "统计类型:0-按月统计,1-按年统计,2-自定义统计", required = true) @RequestParam(required = true) int statsType,
            @ApiParam(value = "统计时间:月格式(yyyy-MM),年格式(yyyy),自定义统计时间开始日期", required = true) @RequestParam(required = true) String startDate,
            @ApiParam(value = "统计时间:年月统计不用传入此参数,自定义统计截至日期", required = false) @RequestParam(required = false) String endDate) throws ParseException {
        LocalDate localDate = LocalDate.now();
        LoginUser loginUser = UserUtil.getCurrentUser();
        SceneEntity sceneEntity = new SceneEntity();
        sceneEntity.setTenantId(loginUser.getTenantId());
        sceneEntity.setProgramItems(loginUser.getProgramItemList());
        sceneEntity.setUserType(loginUser.getType());
        //1是公司，2是公司及以下，3部门，4部门及以下，5自定义
        sceneEntity.setPermissonType(loginUser.getPermissonType());
        sceneEntity.setId(Long.parseLong(String.valueOf(id)));
        switch (statsType) {
            case 0:
                startDate = String.format("%s-01", startDate);
                if(isCurrentMonth(startDate)==true){
                    endDate = String.format("%s-%s", startDate.substring(0,7),localDate.getDayOfMonth()+1);
                }
                else {
                    endDate = subMonth(startDate, 1);
                }
                break;
            case 1:
                startDate = String.format("%s-01-01", startDate);
                if(isCurrentYear(startDate)==true){
                    endDate = String.format("%s-%s-01", localDate.getYear(),localDate.getMonthValue()+1);
                }
                else {
                    endDate = subYear(startDate, 1);
                }
                break;
            case 2:
                startDate = String.format("%s-01", startDate);
                endDate = String.format("%s-01", endDate);

                if(isCurrentMonth(endDate)==true){
                    endDate = String.format("%s-%s", endDate.substring(0,7),localDate.getDayOfMonth()+1);
                }
                else {
                    endDate = subMonth(endDate, 1);
                }
                break;
        }
        List<Map<String,Object>> list = new ArrayList<>();

        if(statsType == 0 || statsType== 2){
            list = sceneService.selectMonthAlarmTimes(sceneEntity, startDate, endDate,sort);
        }
        else if(statsType == 1){
            list = sceneService.selectYearAlarmTimes(sceneEntity, startDate, endDate,sort);
        }
        return new AjaxMessage<>(ResultStatus.OK, list);
    }

    @RequestMapping(value = "/selectAlarmDeviceIdBySenceId", method = RequestMethod.GET)
    @ResponseBody
    @ApiOperation(value = "根据场景ID获取报警设备的ID")
    public AjaxMessage<List<Map<String,Object>>> selectAlarmDeviceIdBySenceId(
            @ApiParam(value = "设备或场景ID", required = true) @RequestParam(required = true) int id){
        List<Map<String,Object>> list = sceneService.selectAlarmDeviceIdBySenceId(id);
        return new AjaxMessage<>(ResultStatus.OK,list);
    }


    @RequestMapping(value = "/selectAlarmLable", method = RequestMethod.GET)
    @ResponseBody
    @ApiOperation(value = "报警标签")
    public AjaxMessage<List<Map<String,Object>>> selectAlarmLable(
            @ApiParam(value = "设备或场景ID", required = true) @RequestParam(required = true) int id,
            @ApiParam(value = "设备或场景标识(1:设备;2:场景)", required = true) @RequestParam(required = true) int sort,
            @ApiParam(value = "统计类型:0-按月统计,1-按年统计,2-自定义统计", required = true) @RequestParam(required = true) int statsType,
            @ApiParam(value = "统计时间:月格式(yyyy-MM),年格式(yyyy),自定义统计时间开始日期", required = true) @RequestParam(required = true) String startDate,
            @ApiParam(value = "统计时间:年月统计不用传入此参数,自定义统计截至日期", required = false) @RequestParam(required = false) String endDate) throws ParseException {
        LocalDate localDate = LocalDate.now();
        SceneEntity sceneEntity = new SceneEntity();
        sceneEntity.setId(Long.parseLong(String.valueOf(id)));
        switch (statsType) {
            case 0:
                startDate = String.format("%s-01", startDate);
                endDate = subMonth(startDate, 1);
                break;
            case 1:
                startDate = String.format("%s-01-01", startDate);
                endDate = subYear(startDate, 1);
                break;
            case 2:
                startDate = String.format("%s-01", startDate);
                endDate = String.format("%s-01", endDate);
                if(isCurrentMonth(endDate)==true){
                   endDate = String.format("%s-%s", endDate.substring(0,7),localDate.getDayOfMonth()+1);
                }
                else {
                    endDate = subMonth(endDate, 1);
                }
                break;
        }
        List<Map<String,Object>> list = sceneService.selectAlarmLable(sceneEntity,startDate,endDate,sort);
        return new AjaxMessage<>(ResultStatus.OK,list);
    }


    /**
     * 获取一个月有多少天
     */
    public int getDaysOfMonth(String date) throws ParseException {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Date dt = sdf.parse(date);
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(dt);
        return calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
    }




    public int differentDaysByMillisecond(String date1,String date2) throws ParseException {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Date dt1 = sdf.parse(date1);
        Date dt2 = sdf.parse(date2);
        int days = (int) ((dt2.getTime() - dt1.getTime()) / (1000*3600*24));
        return days;
    }


    /**
     * 日期是否当前月份
     */
    public boolean isCurrentMonth(String date) throws ParseException {
        LocalDate localDate = LocalDate.now();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Date dt = sdf.parse(date);
        Calendar rightNow = Calendar.getInstance();
        rightNow.setTime(dt);
        int y = rightNow.get(Calendar.YEAR);
        int m =rightNow.get(Calendar.MONTH)+1;
        if( y== localDate.getYear() &&  m == localDate.getMonthValue()){
            return true;
        }
        return false;
    }

    /**
     * 日期增加一年
     */
    private String subYear(String date, int n) throws ParseException {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Date dt = sdf.parse(date);
        Calendar rightNow = Calendar.getInstance();
        rightNow.setTime(dt);
        rightNow.add(Calendar.YEAR, n);
        Date dt1 = rightNow.getTime();
        String reStr = sdf.format(dt1);
        return reStr;
    }

    /**
     * 日期增加一月
     */
    private String subMonth(String date, int n) throws ParseException {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Date dt = sdf.parse(date);
        Calendar rightNow = Calendar.getInstance();
        rightNow.setTime(dt);
        rightNow.add(Calendar.MONTH, n);
        Date dt1 = rightNow.getTime();
        String reStr = sdf.format(dt1);
        return reStr;
    }

    /**
     * 判断是否是整数或者是小数
     * @param str
     * @return true：是，false不是
     */
    public static boolean validateNumber(String str){
        Pattern pattern = Pattern.compile("[0-9]*");
        if(str.indexOf(".")>0){//判断是否有小数点
            if(str.indexOf(".")==str.lastIndexOf(".") && str.split("\\.").length==2){ //判断是否只有一个小数点
                return pattern.matcher(str.replace(".","")).matches();
            }else {
                return false;
            }
        }else {
            return pattern.matcher(str).matches();
        }
    }


    /**
     * 日期是否当前月份
     */
    public boolean isCurrentYear(String date) throws ParseException {
        LocalDate localDate = LocalDate.now();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Date dt = sdf.parse(date);
        Calendar rightNow = Calendar.getInstance();
        rightNow.setTime(dt);
        int y = rightNow.get(Calendar.YEAR);
        if( y== localDate.getYear()){
            return true;
        }
        return false;
    }
}
