package com.ruoyi.ss.device.service;

import com.ruoyi.ss.device.domain.*;
import com.ruoyi.ss.device.domain.dto.DeviceBatchUpdateModelDTO;
import com.ruoyi.ss.device.domain.dto.DeviceRegisterDTO;
import com.ruoyi.ss.device.domain.dto.DeviceWifiDTO;
import com.ruoyi.ss.device.domain.enums.DevicePowerStatus;
import com.ruoyi.ss.device.domain.vo.DeviceMacSnVO;
import com.ruoyi.ss.device.domain.vo.DeviceVO;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;

/**
 * 设备Service接口
 *
 * @author 邱贞招
 * @date 2024-02-21
 */
public interface DeviceService
{
    /**
     * 查询设备
     *
     * @param deviceId 设备主键
     * @return 设备
     */
    public DeviceVO selectById(Long deviceId);

    /**
     * 查询设备列表
     *
     * @param smDevice 设备
     * @return 设备集合
     */
    public List<DeviceVO> selectSmDeviceList(DeviceQuery smDevice);

    /**
     * 新增设备
     *
     * @param device 设备
     * @return 结果
     */
    public int insertSmDevice(Device device);

    /**
     * 修改设备
     *
     * @param device 设备
     * @return 结果
     */
    public int updateSmDevice(DeviceBO device);

    /**
     * 批量删除设备
     *
     * @param deviceIds 需要删除的设备主键集合
     * @return 结果
     */
    public int deleteSmDeviceByDeviceIds(Long[] deviceIds);

    /**
     * 条件查询数量
     * @param dto 查询条件
     * @return 结果
     */
    int selectCount(DeviceQuery dto);

    /**
     * 查询指定店铺下的设备列表
     * @param storeId
     */
    List<DeviceVO> selectSmDeviceByStoreId(Long storeId);

    /**
     * 增加时间
     *
     * @param deviceId 设备id
     * @param seconds  时长（秒）
     * @param withIot  是否充值物联网设备
     * @param reason
     */
    boolean addTime(Long deviceId, long seconds, boolean withIot, String reason);

    boolean addTime(DeviceVO device, long seconds, boolean withIot, String reason);

    /**
     * 逻辑删除
     */
    int logicDel(List<Long> deviceIds);

    /**
     * 通过型号id列表，查询设备列表，并分组
     * @param modelIds 型号id列表
     */
    Map<Long, List<DeviceVO>> selectGroupByModelIds(List<Long> modelIds);

    /**
     * 切换设备通电状态（通/断电）
     *
     * @param device 设备id
     * @param status 通电状态
     * @param reason
     */
    int switchDevice(DeviceVO device, DevicePowerStatus status, String reason);

    /**
     * 拉取设备信息，并保存到数据库
     * @param deviceIds 设备id列表（为空则查询所有）
     */
    void pullDeviceInfo(List<Long> deviceIds);

    /**
     * 拉取设备信息，并保存到数据库
     */
    void pullDeviceInfoList(List<DeviceVO> list);

    /**
     * 通过SN绑定设备
     *
     * @param storeId  店铺ID
     * @param userId
     * @param deviceNo 设备编号（SN）
     */
    String bindBySn(Long storeId, Long userId, String deviceNo);

    /**
     * 通过MAC绑定设备
     */
    String bindByMac(Long storeId, Long userId, String mac);

    /**
     * 商户解绑设备
     *
     * @param deviceId 设备id
     */
    int unbind(Long deviceId);

    /**
     * 通过mac查询设备
     * @param mac mac号
     * @return 设备信息
     */
    DeviceVO selectByMac(String mac);

    /**
     * 归零电表，并关闭订单
     *
     * @param deviceId    设备id
     * @param requiredIot
     * @param totalEle
     * @param reason
     * @param withTime
     * @param withEle
     */
    int resetWithBill(Long deviceId, boolean requiredIot, BigDecimal totalEle, String reason, boolean withTime, boolean withEle);

    /**
     * 设备是否已经被绑定
     *
     * @param mac
     * @return
     */
    int bindCodeByMac(String mac);

    /**
     * ids查询列表
     */
    default List<DeviceVO> selectByIds(List<Long> ids) {
        return selectByIds(ids, null);
    }

    /**
     * ids查询列表
     */
    List<DeviceVO> selectByIds(List<Long> ids, Long userId);

    /**
     * 查询各店铺的设备数量,并分组
     * @param storeIds 店铺id
     */
    Map<Long, Integer> selectCountMapByStoreIds(List<Long> storeIds);

    /**
     * 条件查询数量，并分组
     * @param query 查询条件
     * @param keyMapper 键值的映射
     */
    <K> Map<K, Integer> selectCommonCountMap(DeviceQuery query, Function<? super DeviceCountVO, ? extends K> keyMapper );

    /**
     * 获取设备，包含套餐列表
     * @param deviceNo 设备编码
     * @return
     */
    DeviceVO getDeviceWithSuitList(String deviceNo);

    /**
     * 根据设备编号查询
     */
    DeviceVO selectByDeviceNo(String deviceNo);


    /**
     * 设备绑定SN码
     * @param deviceId 设备ID
     * @param sn SN
     */
    int bindSn(Long deviceId, String sn);

    /**
     * 根据SN码查询设备是否已经绑定
     *
     * @param deviceNo
     * @return
     */
    int bindCodeBySn(String deviceNo);

    /**
     * 更新设备服务费
     */
    int updateServiceRateByUserId(Long userId, BigDecimal serviceRate);

    /**
     * 更新设备信息
     */
    int updateByIot(Device device);

    /**
     * 刷新设备状态，如果过期，则修改为正常
     */
    void freshStatus(DeviceVO device);

    /**
     * 设备心跳，用于检测是否在线
     */
    void deviceHeartBeat();

    /**
     * 设备录入
     */
    int register(DeviceRegisterDTO dto);

    /**
     * 获取所有MAC
     */
    List<DeviceMacSnVO> selectMacSnList(DeviceQuery query);

    /**
     * 查询一个
     */
    DeviceVO selectOne(DeviceQuery query);

    /**
     * 获取当前用户正在使用中的设备
     */
    List<DeviceVO> selectUsingDevice(Long userId);

    /**
     * 开关设备
     */
    int switchDevice(Long deviceId, boolean open, String reason);

    /**
     * 批量更新设备型号
     */
    int batchUpdateModel(DeviceBatchUpdateModelDTO dto);

    /**
     * 更新服务费
     */
    int updateServiceRate(DeviceVO data);

    /**
     * 续费时长
     * @param deviceId 设备ID
     * @param time 时长
     * @param timeUnit 时长单位
     */
    int renewalRentTime(Long deviceId, int time, TimeUnit timeUnit);

    /**
     * 刷新设备数据
     */
    void pullDeviceInfo(Long deviceId);

    /**
     * 设备归零时长
     *
     * @param device   设备
     * @param required 是否必须成功
     * @param reason
     */
    int resetTime(DeviceVO device, boolean required, String reason);

    /**
     * 设备归零电量
     */
    int resetEle(DeviceVO device, boolean required, String reason);

    /**
     * 归零电量
     */
    int resetEle(Long deviceId, boolean required, String reason);

    /**
     * 添加电量
     */
    boolean addEle(Long deviceId, BigDecimal amount, boolean withIot, String reason);

    boolean addEle(DeviceVO device, BigDecimal amount, boolean withIot, String reason);

    int updateLastRecoverTime(Long deviceId, Long lastRecoverTime);

    /**
     * 设置时间
     *
     * @param device     设备
     * @param expireTime 过期时间
     * @param withIot    是否操作设备
     * @param tryCount   尝试次数
     * @param reason
     */
    int setTime(DeviceVO device, LocalDateTime expireTime, boolean withIot, int tryCount, String reason);

    int setWifi(DeviceWifiDTO dto);

    /**
     * 根据mac查询设备
     */
    DeviceVO selectByAnyMac(String mac);

    /**
     * 拉取最新设备数据
     */
    void pullDeviceInfo(DeviceVO device);

    /**
     * 解绑代理商
     */
    int unbindAgent(Long deviceId);

    /**
     * 绑定商户
     */
    String bindMch(Long deviceId, Long mchId);

    /**
     * 查询最大的代理商设备服务费
     */
    BigDecimal selectMaxAgentServiceRate(DeviceQuery query);

    /**
     * 绑定代理商
     * @param  deviceId 设备ID
     * @param agentId 代理商ID
     * @param agentServiceRate 代理商设备服务费
     */
    int bindAgent(Long deviceId, Long agentId, BigDecimal agentServiceRate);

    /**
     * 设置电量
     */
    int setEle(DeviceVO device, BigDecimal ele, int tryCount, String reason);

    /**
     * 设置剩余时间
     */
    int setTime(DeviceVO device, long seconds, int tryCount, String reason);

    /**
     * 查询员工设备列表
     */
    List<DeviceVO> selectStaffDeviceList(DeviceQuery query);

    /**
     * 尝试关闭该设备未结束的所有订单
     * @param device 设备
     * @param totalEle 总用电量
     */
    int closeNotFinishedBill(DeviceVO device, BigDecimal totalEle);

    /**
     * 记录初始化读数
     */
    int initTotalEle(Long deviceId);

    /**
     * 修改电压系数
     */
    int updateVxs(Long deviceId, BigDecimal vxs, String reason);
}
