package com.casic.missiles.modular.system.controller;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.casic.missiles.config.DeviceServerProperties;
import com.casic.missiles.core.application.context.AbstractPermissionContext;
import com.casic.missiles.core.application.service.AbstractDictService;
import com.casic.missiles.core.base.controller.ExportController;
import com.casic.missiles.core.common.annotion.BussinessLog;
import com.casic.missiles.core.common.annotion.Permission;
import com.casic.missiles.core.datascope.DataScope;
import com.casic.missiles.core.page.PageFactory;
import com.casic.missiles.model.exception.ServiceException;
import com.casic.missiles.model.exception.enums.CoreExceptionEnum;
import com.casic.missiles.model.log.LogObjectHolder;
import com.casic.missiles.model.response.ErrorResponseData;
import com.casic.missiles.model.response.ResponseData;
import com.casic.missiles.model.response.SuccessResponseData;
import com.casic.missiles.modular.system.constant.ModularDictConst;
import com.casic.missiles.modular.system.dict.DeviceDict;
import com.casic.missiles.modular.system.dto.DeviceCodeSelectDto;
import com.casic.missiles.modular.system.dto.DeviceDto;
import com.casic.missiles.modular.system.dto.DeviceSelectDto;
import com.casic.missiles.modular.system.enums.DeviceExportHeadersEnum;
import com.casic.missiles.modular.system.model.Device;
import com.casic.missiles.modular.system.model.DeviceModels;
import com.casic.missiles.modular.system.model.DeviceType;
import com.casic.missiles.modular.system.service.IDeviceModelsService;
import com.casic.missiles.modular.system.service.IDeviceService;
import com.casic.missiles.modular.system.service.IDeviceTypeService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static com.casic.missiles.modular.system.constant.DeviceConst.DEVICE_ADD_LOG_KEY;
import static com.casic.missiles.modular.system.constant.DeviceConst.DEVICE_QUERY_DEVICE_TYPE;

/**
 * 设备控制器
 *
 * @author dev
 * @Date 2019-05-23 18:07:55
 */
@Controller
@RequestMapping("/device")
public class DeviceController extends ExportController {
    private static final Logger logger = LoggerFactory.getLogger(DeviceController.class);
    @Resource
    private AbstractDictService dictService;
    @Resource
    private AbstractPermissionContext permissionService;
    @Autowired
    private IDeviceService deviceService;
    @Autowired
    private DeviceServerProperties deviceServerProperties;

    @Autowired
    private IDeviceTypeService deviceTypeService;
    @Autowired
    private IDeviceModelsService deviceModelsService;

    @RequestMapping(value = "/list")
    @ResponseBody
    public Object list(String keywords, String deviceType, String deptid, String beginTime, String endTime, String isOnline) {
        Page<DeviceDto> page = PageFactory.defaultPage();
        //查询数据权限 使用默认DEPTID 字段
        DataScope dataScope = permissionService.getAuthService().getLoginUserDataScope();
        List<DeviceDto> list = deviceService.selectDataScopePage(dataScope, page, deviceType, deptid, beginTime, endTime, keywords, isOnline);
        list.forEach(deviceDto -> {
            deviceDto.setBfztName(dictService.getDictNameByCode(ModularDictConst.BFZT, deviceDto.getBfzt()));
            deviceDto.setOnlineStateName(dictService.getDictNameByCode(ModularDictConst.ONLINESTATUS, deviceDto.getOnlineState()));
        });
        page.setRecords(list);
        return new SuccessResponseData(super.packForBT(page));
    }

    @RequestMapping(value = "/listByConfig")
    @ResponseBody
    public ResponseData listByConfig(String deviceType, String configStatus) {

        DataScope dataScope = permissionService.getAuthService().getLoginUserDataScope();
        List<DeviceCodeSelectDto> list = deviceService.selectDevicesByConfig(dataScope, deviceType, configStatus);
        if (CollectionUtil.isNotEmpty(list)) {
            list.forEach(deviceCodeSelectDto -> {
                deviceCodeSelectDto.setDeptName(permissionService.getDeptService().getDeptName(deviceCodeSelectDto.getDeptId()));
            });
        }
        return new SuccessResponseData(list);
    }


    @GetMapping(value = "/type")
    @ResponseBody
    public Object type() {
        //设备类型列表查询
        List<DeviceType> list = deviceTypeService.list(null);
        List<DeviceSelectDto> selectDtos = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(list)) {
            list.forEach(deviceType -> {
                selectDtos.add(new DeviceSelectDto(deviceType.getTypeName(), deviceType.getId()));
            });
        }
        return ResponseData.success(selectDtos);
    }

    @GetMapping(value = "/model")
    @ResponseBody
    public Object model(String deviceType) {
        //设备类型列表查询
        QueryWrapper<DeviceModels> query = new QueryWrapper<>();
        if (StrUtil.isNotEmpty(deviceType)) {
            query.eq(DEVICE_QUERY_DEVICE_TYPE, deviceType);
        }

        List<DeviceModels> list = deviceModelsService.list(query);
        List<DeviceSelectDto> selectDtos = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(list)) {
            list.forEach(deviceModels -> {
                selectDtos.add(new DeviceSelectDto(deviceModels.getModelName(), deviceModels.getId(), deviceModels.getDeviceType()));
            });
        }
        return ResponseData.success(selectDtos);
    }

    @RequestMapping(value = "/batchImport", method = RequestMethod.POST)
    @Permission
    @ResponseBody
    public Object batchImport(@RequestParam("file") MultipartFile file) {
        List<Device> results = new ArrayList<>();
        //设置表头与字段映射,可通过反射获取
        Map<String, String> mapper = new HashMap<>();
        //判断唯一
        mapper.put("设备编号", "devcode");
        mapper.put("设备名称", "deviceName");
        mapper.put("设备类型", "deviceTypeName");
        mapper.put("设备型号", "modelName");
        mapper.put("井编号", "wellCode");
        mapper.put("数据集中器编号", "concenCode");
        mapper.put("设备安装时间", "installDateFmt");
        try {

            results = this.importExcel(Device.class, file, null, null);
            List<String> list = deviceService.addDeviceBatch(results);

            if (!CollectionUtil.isEmpty(list)) {
                //获取第校验报错信息
                return new ErrorResponseData(list.get(0));
            }


        } catch (Exception e) {
            return catchMybatisPlusException(e, "导入设备失败");
        }

        return ResponseData.success();
    }

    @RequestMapping(value = "/batchExport")
    @Permission
    @ResponseBody
    public void batchExport(HttpServletResponse response, String keywords, String deviceType, String deptid, String beginTime, String endTime, String isOnline) throws IOException {

        Page<DeviceDto> page = PageFactory.defaultPage();
        page.setCurrent(1);
        page.setSearchCount(false);
        page.setSize(Integer.MAX_VALUE);
        DataScope dataScope = permissionService.getAuthService().getLoginUserDataScope();
        List<DeviceDto> list = deviceService.selectDataScopePage(dataScope, page, deviceType, deptid, beginTime, endTime, keywords, isOnline);
        list.forEach(deviceDto -> {
            deviceDto.setBfztName(dictService.getDictNameByCode(ModularDictConst.BFZT, deviceDto.getBfzt()));
            deviceDto.setOnlineStateName(dictService.getDictNameByCode(ModularDictConst.ONLINESTATUS, deviceDto.getOnlineState()));
        });
        //获取导出文件header
        super.exportExcel(DeviceDto.class, list, DeviceExportHeadersEnum.DEVICE_EXPORT.getFileName());

    }

    /**
     * 新增
     */
    @RequestMapping(value = "/add")
    @Permission
    @BussinessLog(value = "添加设备", key = DEVICE_ADD_LOG_KEY, dict = DeviceDict.class)
    @ResponseBody
    public Object add(@Valid Device device, BindingResult result) {
        if (result.hasErrors()) {
            return ResponseData.error(result.getFieldErrors().get(0).getDefaultMessage());
        }

        try {
            deviceService.save(device);
        } catch (Exception e) {
            ServiceException gunsException = new ServiceException(CoreExceptionEnum.REQUEST_NULL);
            String errorMsg = "设备添加失败";
            if (e instanceof DuplicateKeyException) {
                errorMsg = "设备编号重复";
            } else if (e instanceof ServiceException) {
                ServiceException gunException = (ServiceException) e;
                errorMsg = gunException.getMessage();
            }
            logger.error("设备添加失败", e);
            gunsException.setErrorMessage(errorMsg);
            throw gunsException;
        }

        return ResponseData.success();
    }

    private ResponseData catchMybatisPlusException(Exception e, String errorMsg) {
        if (e instanceof MybatisPlusException) {
            MybatisPlusException mybatisPlusException = (MybatisPlusException) e;
            String message = mybatisPlusException.getCause().getCause().getCause().getMessage();
            if (message.contains("Duplicate entry '")) {
                return new ErrorResponseData("设备编号重复:" + message.replaceAll("Duplicate entry '", "").replaceAll("' for key 'DEVCODE'", ""));
            }
        }
        logger.error(errorMsg, e);
        return new ErrorResponseData(errorMsg);
    }

    /**
     * 删除
     */
    @PostMapping(value = "/delete")
    @ResponseBody
    @Permission
    @BussinessLog(value = "删除设备信息")
    public Object delete(@RequestParam List<Long> ids) {
        deviceService.deleteByIds(ids);
        return ResponseData.success();
    }


    /**
     * 修改
     */
    @PostMapping(value = "/update")
    @ResponseBody
    @Permission
    @BussinessLog(value = "修改设备信息", key = DEVICE_ADD_LOG_KEY, dict = DeviceDict.class)
    public Object update(Device device) {
        if (device.getId() == null) {
            throw new ServiceException(CoreExceptionEnum.REQUEST_NULL);
        }
        Device oldDevice = this.deviceService.getById(device.getId());
        LogObjectHolder.me().set(oldDevice);

        deviceService.updateById(device);
        return ResponseData.success();
    }


}
