<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.ems.mapper.ElecConsumeForecastMapper">

    <resultMap type="com.ruoyi.ems.domain.ElecConsumeForecast" id="ElecConsumeForecastResult">
        <result property="id"               column="id"                 />
        <result property="areaCode"         column="area_code"          />
        <result property="objCode"          column="obj_code"           />
        <result property="objType"          column="obj_type"           />
        <result property="date"             column="date"               />
        <result property="elecUseQuantity"  column="elec_use_quantity"  />
        <result property="objName"          column="obj_name"           />
    </resultMap>

    <sql id="selectForecastVo">
        select id, area_code, obj_code, obj_type, date, elec_use_quantity
        from adm_ems_elec_consume_forecast
    </sql>

    <!--
        层级汇总条件片段
        核心逻辑：使用 FIND_IN_SET 函数基于 ancestors 字段查找所有子节点
        当选择父节点时，自动包含该节点及其所有子节点的数据
    -->
    <sql id="hierarchyCondition">
        <choose>
            <!-- 选择特定对象时，查询该对象及所有子对象 -->
            <when test="objCode != null and objCode != '' and objCode != '-1'">
                AND (
                f.obj_code = #{objCode}
                OR f.obj_code IN (
                SELECT area_code FROM adm_area
                WHERE FIND_IN_SET(#{objCode}, ancestors) > 0
                )
                )
            </when>
            <!-- 选择特定区域时，查询该区域及其下所有子区域 -->
            <when test="areaCode != null and areaCode != '' and areaCode != '-1'">
                AND (
                f.obj_code = #{areaCode}
                OR f.obj_code IN (
                SELECT area_code FROM adm_area
                WHERE area_code = #{areaCode}
                OR FIND_IN_SET(#{areaCode}, ancestors) > 0
                )
                )
            </when>
        </choose>
    </sql>

    <!--
        查询预测列表（支持层级汇总）
        点击父节点时显示所有子节点数据
    -->
    <select id="selectForecastList" parameterType="com.ruoyi.ems.domain.ElecConsumeForecast" resultMap="ElecConsumeForecastResult">
        SELECT
        f.id,
        f.area_code,
        f.obj_code,
        f.obj_type,
        f.date,
        f.elec_use_quantity,
        COALESCE(a.area_name, fc.facs_name, d.device_name) AS obj_name
        FROM adm_ems_elec_consume_forecast f
        LEFT JOIN adm_area a ON f.obj_code = a.area_code AND f.obj_type = 1
        LEFT JOIN adm_ems_facs fc ON f.obj_code = fc.facs_code AND f.obj_type = 2
        LEFT JOIN adm_ems_device d ON f.obj_code = d.device_code AND f.obj_type = 3
        <where>
            <if test="objType != null">
                AND f.obj_type = #{objType}
            </if>
            <if test="startRecTime != null and startRecTime != ''">
                AND f.date &gt;= #{startRecTime}
            </if>
            <if test="endRecTime != null and endRecTime != ''">
                AND f.date &lt;= #{endRecTime}
            </if>
            <!-- 层级汇总条件 -->
            <include refid="hierarchyCondition"/>
        </where>
        ORDER BY f.date DESC, f.obj_code
    </select>

    <select id="selectForecastById" parameterType="Long" resultMap="ElecConsumeForecastResult">
        <include refid="selectForecastVo"/>
        WHERE id = #{id}
    </select>

    <!--
        每日汇总趋势查询（支持层级汇总）
        用于图表展示，按日期分组汇总用电量
    -->
    <select id="calcForecastDateRange" parameterType="com.ruoyi.ems.domain.ElecConsumeForecast" resultMap="ElecConsumeForecastResult">
        SELECT
        SUM(COALESCE(CAST(f.elec_use_quantity AS DECIMAL(10, 2)), 0)) AS elec_use_quantity,
        f.date
        FROM adm_ems_elec_consume_forecast f
        <where>
            <if test="objType != null">
                AND f.obj_type = #{objType}
            </if>
            <if test="objType == null">
                AND f.obj_type = 1
            </if>
            <if test="startRecTime != null and startRecTime != ''">
                AND f.date &gt;= #{startRecTime}
            </if>
            <if test="endRecTime != null and endRecTime != ''">
                AND f.date &lt;= #{endRecTime}
            </if>
            <!-- 层级汇总条件 -->
            <include refid="hierarchyCondition"/>
        </where>
        GROUP BY f.date
        ORDER BY f.date ASC
    </select>

    <!--
        汇总统计查询（支持层级汇总）
        返回：总用电量、平均用电量、子项数量、天数、日期范围
    -->
    <select id="selectForecastSummary" parameterType="com.ruoyi.ems.domain.ElecConsumeForecast" resultType="java.util.Map">
        SELECT
        COUNT(DISTINCT f.obj_code) AS itemCount,
        COALESCE(SUM(CAST(f.elec_use_quantity AS DECIMAL(10, 2))), 0) AS totalElec,
        COALESCE(AVG(daily_sum.daily_elec), 0) AS avgElec,
        MIN(f.date) AS startDate,
        MAX(f.date) AS endDate,
        COUNT(DISTINCT f.date) AS dayCount
        FROM adm_ems_elec_consume_forecast f
        LEFT JOIN (
        -- 子查询：计算每日汇总，用于计算日均值
        SELECT
        f2.date,
        SUM(CAST(f2.elec_use_quantity AS DECIMAL(10, 2))) AS daily_elec
        FROM adm_ems_elec_consume_forecast f2
        <where>
            <if test="objType != null">
                AND f2.obj_type = #{objType}
            </if>
            <if test="objType == null">
                AND f2.obj_type = 1
            </if>
            <if test="startRecTime != null and startRecTime != ''">
                AND f2.date &gt;= #{startRecTime}
            </if>
            <if test="endRecTime != null and endRecTime != ''">
                AND f2.date &lt;= #{endRecTime}
            </if>
            <choose>
                <when test="objCode != null and objCode != '' and objCode != '-1'">
                    AND (
                    f2.obj_code = #{objCode}
                    OR f2.obj_code IN (
                    SELECT area_code FROM adm_area
                    WHERE FIND_IN_SET(#{objCode}, ancestors) > 0
                    )
                    )
                </when>
                <when test="areaCode != null and areaCode != '' and areaCode != '-1'">
                    AND (
                    f2.obj_code = #{areaCode}
                    OR f2.obj_code IN (
                    SELECT area_code FROM adm_area
                    WHERE area_code = #{areaCode}
                    OR FIND_IN_SET(#{areaCode}, ancestors) > 0
                    )
                    )
                </when>
            </choose>
        </where>
        GROUP BY f2.date
        ) daily_sum ON f.date = daily_sum.date
        <where>
            <if test="objType != null">
                AND f.obj_type = #{objType}
            </if>
            <if test="objType == null">
                AND f.obj_type = 1
            </if>
            <if test="startRecTime != null and startRecTime != ''">
                AND f.date &gt;= #{startRecTime}
            </if>
            <if test="endRecTime != null and endRecTime != ''">
                AND f.date &lt;= #{endRecTime}
            </if>
            <!-- 层级汇总条件 -->
            <include refid="hierarchyCondition"/>
        </where>
    </select>

    <!-- 新增单条记录 -->
    <insert id="insertForecast" parameterType="com.ruoyi.ems.domain.ElecConsumeForecast" useGeneratedKeys="true" keyProperty="id">
        INSERT INTO adm_ems_elec_consume_forecast
        <trim prefix="(" suffix=")" suffixOverrides=",">
            <if test="areaCode != null and areaCode != ''">area_code,</if>
            <if test="objCode != null and objCode != ''">obj_code,</if>
            <if test="objType != null">obj_type,</if>
            <if test="date != null">date,</if>
            <if test="elecUseQuantity != null">elec_use_quantity,</if>
        </trim>
        <trim prefix="VALUES (" suffix=")" suffixOverrides=",">
            <if test="areaCode != null and areaCode != ''">#{areaCode},</if>
            <if test="objCode != null and objCode != ''">#{objCode},</if>
            <if test="objType != null">#{objType},</if>
            <if test="date != null">#{date},</if>
            <if test="elecUseQuantity != null">#{elecUseQuantity},</if>
        </trim>
    </insert>

    <!-- 批量新增 -->
    <insert id="insertBatch" parameterType="java.util.List">
        INSERT INTO adm_ems_elec_consume_forecast
        (area_code, obj_code, obj_type, date, elec_use_quantity)
        VALUES
        <foreach collection="list" item="item" index="index" separator=",">
            (#{item.areaCode}, #{item.objCode}, #{item.objType}, #{item.date}, #{item.elecUseQuantity})
        </foreach>
    </insert>

    <!-- 更新记录 -->
    <update id="updateForecast" parameterType="com.ruoyi.ems.domain.ElecConsumeForecast">
        UPDATE adm_ems_elec_consume_forecast
        <trim prefix="SET" suffixOverrides=",">
            <if test="areaCode != null and areaCode != ''">area_code = #{areaCode},</if>
            <if test="objCode != null and objCode != ''">obj_code = #{objCode},</if>
            <if test="objType != null">obj_type = #{objType},</if>
            <if test="date != null">date = #{date},</if>
            <if test="elecUseQuantity != null">elec_use_quantity = #{elecUseQuantity},</if>
        </trim>
        WHERE id = #{id}
    </update>

    <!-- 删除单条记录 -->
    <delete id="deleteForecastById" parameterType="Long">
        DELETE FROM adm_ems_elec_consume_forecast WHERE id = #{id}
    </delete>

    <!-- 按条件删除 -->
    <delete id="deleteByCondition">
        DELETE FROM adm_ems_elec_consume_forecast
        WHERE area_code = #{areaCode}
          AND obj_type = #{objType}
          AND obj_code = #{objCode}
          AND date BETWEEN #{startTime} AND #{endTime}
    </delete>

    <!-- 批量删除 -->
    <delete id="deleteForecastByIds" parameterType="String">
        DELETE FROM adm_ems_elec_consume_forecast WHERE id IN
        <foreach item="id" collection="array" open="(" separator="," close=")">
            #{id}
        </foreach>
    </delete>

</mapper>