package com.ruoyi.web.bst;

import java.util.List;

import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.ruoyi.bst.area.service.AreaValidator;
import com.ruoyi.bst.areaJoin.domain.enums.AreaJoinPermission;
import com.ruoyi.bst.device.domain.Device;
import com.ruoyi.bst.device.domain.DeviceQuery;
import com.ruoyi.bst.device.domain.DeviceVO;
import com.ruoyi.bst.device.domain.dto.DeviceTransferDTO;
import com.ruoyi.bst.device.service.DeviceAssembler;
import com.ruoyi.bst.device.service.DeviceConverter;
import com.ruoyi.bst.device.service.DeviceIotService;
import com.ruoyi.bst.device.service.DeviceService;
import com.ruoyi.bst.device.service.DeviceValidator;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.core.validate.ValidGroup;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.enums.LogBizType;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.iot.constants.IotConstants;
import com.ruoyi.system.user.service.UserValidator;

/**
 * 设备Controller
 *
 * @author ruoyi
 * @date 2025-03-20
 */
@RestController
@RequestMapping("/bst/device")
public class DeviceController extends BaseController {
    @Autowired
    private DeviceService deviceService;

    @Autowired
    private DeviceConverter deviceConverter;

    @Autowired
    private UserValidator userValidator;

    @Autowired
    private DeviceValidator deviceValidator;

    @Autowired
    private AreaValidator areaValidator;

    @Autowired
    private DeviceIotService deviceIotService;

    @Autowired
    private DeviceAssembler deviceAssembler;

    /**
     * 查询设备列表
     */
    @PreAuthorize("@ss.hasPermi('bst:device:list')")
    @GetMapping("/list")
    public TableDataInfo list(DeviceQuery query) {
        startPage();
        startOrderBy();
        query.setScope(true);
        query.addAreaPermission(AreaJoinPermission.DEVICE_VIEW.getCode());
        List<DeviceVO> list = deviceService.selectDeviceList(query);
        if (query.getRefresh() != null && query.getRefresh()) {
            deviceIotService.refresh(list, IotConstants.ONLINE_TYPE_COMMAND);
        }
        return getDataTable(list);
    }

    /**
     * 查询全部设备列表
     */
    @PreAuthorize("@ss.hasPermi('bst:device:list')")
    @GetMapping("/all")
    public AjaxResult all(DeviceQuery query) {
        if (query.getAreaId() == null) {
            return error("运营区ID不能为空");
        }
        query.setScope(true);
        query.addAreaPermission(AreaJoinPermission.DEVICE_VIEW.getCode());
        List<DeviceVO> list = deviceService.selectDeviceList(query);
        if (query.getRefresh() != null && query.getRefresh()) {
            deviceIotService.refresh(list, IotConstants.ONLINE_TYPE_COMMAND);
        }
        return success(list);
    }

    /**
     * 导出设备列表
     */
    @PreAuthorize("@ss.hasPermi('bst:device:export')")
    @Log(title = "设备", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(HttpServletResponse response, DeviceQuery query) {
        query.setScope(true);
        query.addAreaPermission(AreaJoinPermission.DEVICE_VIEW.getCode());
        List<DeviceVO> list = deviceService.selectDeviceList(query);
        ExcelUtil<DeviceVO> util = new ExcelUtil<DeviceVO>(DeviceVO.class);
        util.exportExcel(response, list, "设备数据");
    }

    /**
     * 获取设备详细信息
     */
    @PreAuthorize("@ss.hasPermi('bst:device:query')")
    @GetMapping
    public AjaxResult getInfo(@RequestParam(required = false) Long id,
            @RequestParam(required = false) String sn,
            @RequestParam(required = false, defaultValue = "false") Boolean refresh) {
        DeviceVO device = deviceService.selectDevice(id, sn, true, AreaJoinPermission.DEVICE_VIEW);

        if (refresh) {
            deviceIotService.refresh(device, IotConstants.ONLINE_TYPE_COMMAND);
        }

        return success(device);
    }

    /**
     * 新增设备
     */
    @PreAuthorize("@ss.hasPermi('bst:device:add')")
    @Log(title = "新增设备", businessType = BusinessType.INSERT, bizIdName = "arg0", bizType = LogBizType.DEVICE)
    @PostMapping
    public AjaxResult add(@RequestBody @Validated(ValidGroup.Create.class) Device data) {
        if (!userValidator.canView(data.getMchId())) {
            return error("您无权将该设备绑定到ID为" + data.getMchId() + "的用户上");
        }
        deviceConverter.toPoByCreate(data);
        return toAjax(deviceService.insertDevice(data));
    }

    /**
     * 修改设备
     */
    @PreAuthorize("@ss.hasPermi('bst:device:edit')")
    @Log(title = "修改设备", businessType = BusinessType.UPDATE, bizIdName = "arg0", bizType = LogBizType.DEVICE)
    @PutMapping
    public AjaxResult edit(@RequestBody @Validated(ValidGroup.Update.class) Device data) {
        if (!deviceValidator.canEdit(data.getId())) {
            return error("您无权修改ID为" + data.getId() + "的设备");
        }
        if (!userValidator.canView(data.getMchId())) {
            return error("您无权将该设备绑定到ID为" + data.getMchId() + "的用户上");
        }
        if (!areaValidator.canViewArea(data.getAreaId())) {
            return error("您无权将该设备绑定到ID为" + data.getAreaId() + "的运营区上");
        }
        deviceConverter.toPoByUpdate(data);
        return toAjax(deviceService.updateDevice(data));
    }

    /**
     * 删除设备
     */
    @PreAuthorize("@ss.hasPermi('bst:device:remove')")
    @Log(title = "删除设备", businessType = BusinessType.DELETE, bizIdName = "arg0", bizType = LogBizType.DEVICE)
    @DeleteMapping("/{ids}")
    public AjaxResult remove(@PathVariable List<Long> ids) {
        if (!deviceValidator.canDeleteAll(ids)) {
            return error("您无权删除ID为" + ids + "的设备");
        }
        return toAjax(deviceService.logicDel(ids));
    }

    /**
     * 入仓
     */
    @PreAuthorize("@ss.hasPermi('bst:device:in')")
    @Log(title = "设备入仓", businessType = BusinessType.OTHER, bizIdName = "arg0", bizType = LogBizType.DEVICE)
    @PutMapping("/in")
    public AjaxResult in(@RequestBody List<Long> ids) {
        if (!deviceValidator.canOperate(ids)) {
            return error("您无权入仓ID为" + ids + "的设备");
        }
        List<DeviceVO> deviceList = deviceService.selectDeviceByIds(ids, true, AreaJoinPermission.DEVICE_EDIT);
        int count = deviceService.in(deviceList);
        if (count == 0) {
            return error("入仓失败");
        }
        return success(count);
    }

    /**
     * 出仓
     */
    @PreAuthorize("@ss.hasPermi('bst:device:out')")
    @Log(title = "设备出仓", businessType = BusinessType.OTHER, bizIdName = "arg0", bizType = LogBizType.DEVICE)
    @PutMapping("/out")
    public AjaxResult out(@RequestBody List<Long> ids) {
        if (!deviceValidator.canOperate(ids)) {
            return error("您无权出仓ID为" + ids + "的设备");
        }
        List<DeviceVO> deviceList = deviceService.selectDeviceByIds(ids, true, AreaJoinPermission.DEVICE_EDIT);
        int count = deviceService.out(deviceList);
        if (count == 0) {
            return error("出仓失败");
        }
        return success(count);
    }

    /**
     * 禁用
     */
    @PreAuthorize("@ss.hasPermi('bst:device:disable')")
    @Log(title = "设备禁用", businessType = BusinessType.OTHER, bizIdName = "arg0", bizType = LogBizType.DEVICE)
    @PutMapping("/disable")
    public AjaxResult disable(@RequestBody List<Long> ids) {
        if (!deviceValidator.canOperate(ids)) {
            return error("您无权禁用ID为" + ids + "的设备");
        }
        List<DeviceVO> deviceList = deviceService.selectDeviceByIds(ids, true, AreaJoinPermission.DEVICE_EDIT);
        int count = deviceService.disable(deviceList);
        if (count == 0) {
            return error("禁用失败");
        }
        return success(count);
    }

    /**
     * 启用
     */
    @PreAuthorize("@ss.hasPermi('bst:device:enable')")
    @Log(title = "设备启用", businessType = BusinessType.OTHER, bizIdName = "arg0", bizType = LogBizType.DEVICE)
    @PutMapping("/enable")
    public AjaxResult enable(@RequestBody List<Long> ids) {
        if (!deviceValidator.canOperate(ids)) {
            return error("您无权启用ID为" + ids + "的设备");
        }
        List<DeviceVO> deviceList = deviceService.selectDeviceByIds(ids, true, AreaJoinPermission.DEVICE_EDIT);
        int count = deviceService.enable(deviceList);
        if (count == 0) {
            return error("启用失败");
        }
        return success(count);
    }

    /**
     * 划拨运营区
     */
    @PreAuthorize("@ss.hasPermi('bst:device:transfer')")
    @Log(title = "设备划拨运营区", businessType = BusinessType.OTHER, bizIdName = "arg0", bizType = LogBizType.DEVICE)
    @PutMapping("/transfer")
    public AjaxResult transfer(@RequestBody @Validated DeviceTransferDTO dto) {
        if (!deviceValidator.canOperate(dto.getIds())) {
            return error("您无权划拨ID为" + dto.getIds() + "的设备");
        }
        if (!areaValidator.canEdit(dto.getAreaId())) {
            return error("您无权将设备划拨到ID为" + dto.getAreaId() + "的运营区");
        }
        List<DeviceVO> deviceList = deviceService.selectDeviceByIds(dto.getIds(), true, AreaJoinPermission.DEVICE_EDIT);
        int count = deviceService.transfer(deviceList, dto.getAreaId());
        if (count == 0) {
            return error("划拨失败");
        }
        return success(count);
    }

    /**
     * 解绑所属用户
     */
    @PreAuthorize("@ss.hasPermi('bst:device:unbindMch')")
    @Log(title = "设备解绑所属用户", businessType = BusinessType.OTHER, bizIdName = "arg0", bizType = LogBizType.DEVICE)
    @PutMapping("/unbindMch")
    public AjaxResult unbindMch(@RequestBody List<Long> ids) {
        if (!deviceValidator.canOperate(ids)) {
            return error("您无权解绑ID为" + ids + "的设备");
        }
        List<DeviceVO> deviceList = deviceService.selectDeviceByIds(ids, true, AreaJoinPermission.DEVICE_EDIT);
        int count = deviceService.unbindMch(deviceList);
        if (count == 0) {
            return error("解绑失败");
        }
        return success(count);
    }

    /**
     * 解绑运营区
     */
    @PreAuthorize("@ss.hasPermi('bst:device:unbindArea')")
    @Log(title = "设备解绑运营区", businessType = BusinessType.OTHER, bizIdName = "arg0", bizType = LogBizType.DEVICE)
    @PutMapping("/unbindArea")
    public AjaxResult unbindArea(@RequestBody List<Long> ids) {
        if (!deviceValidator.canOperate(ids)) {
            return error("您无权解绑ID为" + ids + "的设备");
        }
        List<DeviceVO> deviceList = deviceService.selectDeviceByIds(ids, true, AreaJoinPermission.DEVICE_EDIT);
        int count = deviceService.unbindArea(deviceList);
        if (count == 0) {
            return error("解绑失败");
        }
        return success(count);
    }

    /**
     * 查询MAC对应的SN
     */
    @PreAuthorize("@ss.hasPermi('bst:device:list')")
    @PostMapping("/listSnByMac")
    public AjaxResult listSnByMac(@RequestBody List<String> macList) {
        return success(deviceService.listSnByMac(macList));
    }

}
