package cn.iocoder.yudao.module.pms.dal.mysql.iotdevicerunlog;

import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
import cn.iocoder.yudao.module.pms.controller.admin.iotdevicerunlog.vo.IotDeviceRunLogPageReqVO;
import cn.iocoder.yudao.module.pms.controller.admin.iotdevicerunlog.vo.IotDeviceRunLogRespVO;
import cn.iocoder.yudao.module.pms.controller.admin.stat.vo.YearTotalGas;
import cn.iocoder.yudao.module.pms.dal.dataobject.iotdevicerunlog.IotDeviceRunLogDO;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.Year;
import java.util.Collection;
import java.util.List;

/**
 * 设备运行数据记录 中间表 Mapper
 *
 * @author ruiqi
 */
@Mapper
public interface IotDeviceRunLogMapper extends BaseMapperX<IotDeviceRunLogDO> {

    default PageResult<IotDeviceRunLogDO> selectPage(IotDeviceRunLogPageReqVO reqVO) {
        return selectPage(reqVO, new LambdaQueryWrapperX<IotDeviceRunLogDO>()
                .eqIfPresent(IotDeviceRunLogDO::getDeptId, reqVO.getDeptId())
                .eqIfPresent(IotDeviceRunLogDO::getDeviceId, reqVO.getDeviceId())
                .eqIfPresent(IotDeviceRunLogDO::getDeviceCode, reqVO.getDeviceCode())
                .eqIfPresent(IotDeviceRunLogDO::getDeviceComp, reqVO.getDeviceComp())
                .eqIfPresent(IotDeviceRunLogDO::getPointCode, reqVO.getPointCode())
                .likeIfPresent(IotDeviceRunLogDO::getPointName, reqVO.getPointName())
                .eqIfPresent(IotDeviceRunLogDO::getType, reqVO.getType())
                .eqIfPresent(IotDeviceRunLogDO::getValue, reqVO.getValue())
                .eqIfPresent(IotDeviceRunLogDO::getFillContent, reqVO.getFillContent())
                .betweenIfPresent(IotDeviceRunLogDO::getTime, reqVO.getTime())
                .betweenIfPresent(IotDeviceRunLogDO::getDailyRunTime, reqVO.getDailyRunTime())
                .betweenIfPresent(IotDeviceRunLogDO::getTotalRunTime, reqVO.getTotalRunTime())
                .eqIfPresent(IotDeviceRunLogDO::getDailyMileage, reqVO.getDailyMileage())
                .eqIfPresent(IotDeviceRunLogDO::getTotalMileage, reqVO.getTotalMileage())
                .eqIfPresent(IotDeviceRunLogDO::getRemark, reqVO.getRemark())
                .betweenIfPresent(IotDeviceRunLogDO::getCreateTime, reqVO.getCreateTime())
                .orderByDesc(IotDeviceRunLogDO::getId));
    }

    default List<IotDeviceRunLogDO> selectList(IotDeviceRunLogPageReqVO reqVO) {
        return selectList(new LambdaQueryWrapperX<IotDeviceRunLogDO>()
                .eqIfPresent(IotDeviceRunLogDO::getDeptId, reqVO.getDeptId())
                .eqIfPresent(IotDeviceRunLogDO::getDeviceId, reqVO.getDeviceId())
                .inIfPresent(IotDeviceRunLogDO::getDeviceId, reqVO.getDeviceIds())
                .eqIfPresent(IotDeviceRunLogDO::getDeviceCode, reqVO.getDeviceCode())
                .eqIfPresent(IotDeviceRunLogDO::getDeviceComp, reqVO.getDeviceComp())
                .eqIfPresent(IotDeviceRunLogDO::getPointCode, reqVO.getPointCode())
                .likeIfPresent(IotDeviceRunLogDO::getPointName, reqVO.getPointName())
                .eqIfPresent(IotDeviceRunLogDO::getType, reqVO.getType())
                .eqIfPresent(IotDeviceRunLogDO::getValue, reqVO.getValue())
                .eqIfPresent(IotDeviceRunLogDO::getFillContent, reqVO.getFillContent())
                .betweenIfPresent(IotDeviceRunLogDO::getTime, reqVO.getTime())
                .betweenIfPresent(IotDeviceRunLogDO::getDailyRunTime, reqVO.getDailyRunTime())
                .betweenIfPresent(IotDeviceRunLogDO::getTotalRunTime, reqVO.getTotalRunTime())
                .eqIfPresent(IotDeviceRunLogDO::getDailyMileage, reqVO.getDailyMileage())
                .eqIfPresent(IotDeviceRunLogDO::getTotalMileage, reqVO.getTotalMileage())
                .eqIfPresent(IotDeviceRunLogDO::getRemark, reqVO.getRemark())
                .eqIfPresent(IotDeviceRunLogDO::getIsSum, reqVO.getIsSum())
                .betweenIfPresent(IotDeviceRunLogDO::getCreateTime, reqVO.getCreateTime())
                .apply(StrUtil.isNotBlank(reqVO.getCreateTimeStr()),
                        "DATE(create_time) = {0}", reqVO.getCreateTimeStr()));
    }

    /**
     * 查询指定设备 运行记录模板属性对应的累计时长 累计里程
     * @param deviceIds
     * @return
     */
    List<IotDeviceRunLogRespVO> distinctDevices(@Param("deviceIds") Collection<Long> deviceIds,
                                                @Param("deviceCategoryIds") Collection<Long> deviceCategoryIds,
                                                @Param("actualStartTime") String actualStartTime);

    /**
     * 查询指定设备 运行记录模板属性对应的累计时长 累计里程
     * @param deviceIds
     * @return
     */
    List<IotDeviceRunLogRespVO> distinctDevicesSearch(@Param("deviceIds") Collection<Long> deviceIds);

    /**
     * 查询运行记录模板中正常的累积类型属性
     * @param deviceCategoryIds
     * @return
     */
    List<IotDeviceRunLogRespVO> normalCumulativeAttrs(@Param("deviceCategoryIds") Collection<Long> deviceCategoryIds);

    /**
     * 查询指定设备 运行记录模板属性对应的累计时长 累计里程
     * @param deviceIds
     * @return
     */
    List<IotDeviceRunLogRespVO> multipleAccumulatedData(@Param("deviceIds") Collection<Long> deviceIds,
                                                        @Param("attrNames") Collection<String> attrName,
                                                        @Param("actualStartTime") String actualStartTime);


    /**
     * 查询指定设备 运行记录模板属性对应的累计时长 累计里程
     * @param deviceId
     * @return
     */
    BigDecimal theMaxTotalRuntime(@Param("deviceId") Long deviceId,
                                  @Param("pointName") String pointName);

    @TenantIgnore
    List<IotDeviceRunLogRespVO> selectListByCreateTimeAndDeptList(IotDeviceRunLogPageReqVO reqVO);
    @TenantIgnore
    List<YearTotalGas> selectYearTotalGas(IotDeviceRunLogPageReqVO reqVO);

    /**
     * 查询当年"当日注气量"累计值
     * @param deptId 部门ID
     * @param deviceIds 设备ID集合
     * @return fill_content字段数值总和
     */
    /* @TenantIgnore
    @Select("SELECT SUM(CAST(fill_content AS DECIMAL(15,3))) " +
            "FROM rq_iot_device_run_log " +
            "WHERE dept_id = #{deptId} " +
            "AND device_id IN (${deviceIds}) " +
            "AND point_name = '当日注气量' " +
            "AND create_time BETWEEN #{startOfYear} AND #{currentTime}")
    BigDecimal selectCurrentYearFillContentSum(@Param("deptId") Long deptId,
                                               @Param("deviceIds") Collection<Long> deviceIds,
                                               @Param("startOfYear") LocalDateTime startOfYear,
                                               @Param("currentTime") LocalDateTime currentTime); */

    @TenantIgnore
    @Select("<script>" +
            "SELECT SUM(CAST(fill_content AS DECIMAL(15,3))) " +
            "FROM rq_iot_device_run_log " +
            "WHERE dept_id = #{deptId} " +
            "AND device_id IN " +
            "  <foreach item='id' collection='deviceIds' open='(' separator=',' close=')'>" +
            "    #{id}" +
            "  </foreach>" +
            "AND point_name = '当日注气量' " +
            "AND create_time BETWEEN #{startOfYear} AND #{currentTime}" +
            "</script>")
    BigDecimal selectCurrentYearFillContentSum(@Param("deptId") Long deptId,
                                               @Param("deviceIds") Collection<Long> deviceIds,
                                               @Param("startOfYear") LocalDateTime startOfYear,
                                               @Param("currentTime") LocalDateTime currentTime);

    // 可以在Service层提供便捷方法
    @TenantIgnore
    default BigDecimal selectCurrentYearFillContentSum(Long deptId, Collection<Long> deviceIds) {
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime startOfYear = LocalDate.of(Year.now().getValue(), 1, 1).atStartOfDay();
        return selectCurrentYearFillContentSum(deptId, deviceIds, startOfYear, now);
    }
}
