<?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.manage.mapper.FacilityBookingMapper">
    <!--
      模块：功能房预约
      说明：
        - 状态：pending/approved/ongoing/finished/rejected 等，具体语义见领域模型；删除采用 del_flag。
        - 时间轴查询按房间聚合片段；冲突判定仅统计未取消类状态。
        - 审核列表支持多维度筛选；注意 applicantId 与用户名解析在上层完成。
    -->

    <resultMap id="BookingResult" type="com.ruoyi.manage.domain.FacilityBooking">
        <id property="id" column="id"/>
        <result property="roomId" column="room_id"/>
        <result property="applicantId" column="applicant_id"/>
        <result property="applicantUserName" column="applicant_user_name"/>
        <result property="applicantNickName" column="applicant_nick_name"/>
        <result property="purpose" column="purpose"/>
        <result property="startTime" column="start_time"/>
        <result property="endTime" column="end_time"/>
        <result property="durationMinutes" column="duration_minutes"/>
        <result property="status" column="status"/>
        <result property="rejectReason" column="reject_reason"/>
        <result property="createBy" column="create_by"/>
        <result property="createTime" column="create_time"/>
        <result property="updateBy" column="update_by"/>
        <result property="updateTime" column="update_time"/>
        <result property="delFlag" column="del_flag"/>
    </resultMap>

    <resultMap id="TimelineSegment" type="com.ruoyi.manage.vo.TimelineSegmentVO">
        <id property="id" column="id"/>
        <result property="start" column="start_time"/>
        <result property="end" column="end_time"/>
        <result property="status" column="status_text"/>
    </resultMap>

    <sql id="baseSelect">select *
                         from tb_facility_booking</sql>

    <select id="selectById" parameterType="long" resultMap="BookingResult">
        <include refid="baseSelect"/>
        where id = #{id}
    </select>

    <insert id="insert" parameterType="com.ruoyi.manage.domain.FacilityBooking" useGeneratedKeys="true"
            keyProperty="id">
        insert into tb_facility_booking(room_id, applicant_id, purpose, start_time, end_time, duration_minutes, status,
                                        create_by, create_time, del_flag)
        values (#{roomId}, #{applicantId}, #{purpose}, #{startTime}, #{endTime}, #{durationMinutes}, #{status},
                #{createBy}, #{createTime}, '0')
    </insert>

    <update id="update" parameterType="com.ruoyi.manage.domain.FacilityBooking">
        update tb_facility_booking
        <set>
            <if test="purpose != null">purpose = #{purpose},</if>
            <if test="startTime != null">start_time = #{startTime},</if>
            <if test="endTime != null">end_time = #{endTime},</if>
            <if test="durationMinutes != null">duration_minutes = #{durationMinutes},</if>
            <if test="status != null">status = #{status},</if>
            <if test="rejectReason != null">reject_reason = #{rejectReason},</if>
            <if test="updateBy != null">update_by = #{updateBy},</if>
            <if test="updateTime != null">update_time = #{updateTime},</if>
        </set>
        where id = #{id}
    </update>

    <select id="selectMyList" resultMap="BookingResult">
        <include refid="baseSelect"/>
        where del_flag='0' and applicant_id = #{applicantId}
        <if test="status != null and status != ''">and status = #{status}</if>
        order by start_time desc, id desc
    </select>

    <!-- 与 pending/approved/ongoing 冲突：status in ('0','1','4') 并且区间重叠 -->
    <select id="countConflict" resultType="int">
        select count(1) from tb_facility_booking
        where del_flag='0'
        and room_id = #{roomId}
        and status in ('0','1','4')
        and not (end_time &lt;= #{start} or start_time &gt;= #{end})
        <if test="excludeId != null">and id &lt;&gt; #{excludeId}</if>
    </select>

    <select id="selectTimeline" resultMap="TimelineSegment">
        select id,
        start_time,
        end_time,
        case status when '0' then 'pending' when '1' then 'approved' when '4' then 'ongoing' when '5' then 'completed'
        else 'unknown' end as status_text
        from tb_facility_booking
        where del_flag='0' and room_id = #{roomId}
        and status in ('0','1','4','5')
        <if test="from != null">and end_time &gt;= #{from}</if>
        <if test="to != null">and start_time &lt;= #{to}</if>
        order by start_time asc
    </select>

    <select id="countUsersExist" resultType="int">
        select count(1) from sys_user where user_id in
        <foreach collection="userIds" item="id" open="(" separator="," close=")">#{id}</foreach>
    </select>

    <!-- 审核列表：仅 pending，支持按楼栋/房间/申请人/时间范围筛选 -->
    <select id="selectAuditList" resultMap="BookingResult">
        select b.*, u.user_name as applicant_user_name, u.nick_name as applicant_nick_name from tb_facility_booking b
        <if test="buildingId != null">
            inner join tb_facility_room r on r.id = b.room_id
        </if>
        <if test="buildingId != null">
            inner join tb_facility_building bd on bd.id = r.building_id
        </if>
        left join sys_user u on u.user_id = b.applicant_id
        where b.del_flag='0' and b.status = '0'
        <if test="bookingId != null">and b.id = #{bookingId}</if>
        <if test="roomId != null">and b.room_id = #{roomId}</if>
        <if test="buildingId != null">and bd.id = #{buildingId}</if>
        <if test="applicantId != null">and b.applicant_id = #{applicantId}</if>
        <if test="from != null">and b.end_time &gt;= #{from}</if>
        <if test="to != null">and b.start_time &lt;= #{to}</if>
        order by b.start_time asc, b.id asc
    </select>

    <update id="doApprove">
        update tb_facility_booking
        set status      = '1',
            update_time = #{auditTime},
            update_by   = #{auditBy}
        where id = #{id}
          and status = '0'
    </update>

    <update id="doReject">
        update tb_facility_booking
        set status        = '2',
            reject_reason = #{reason},
            update_time   = #{auditTime},
            update_by     = #{auditBy}
        where id = #{id}
          and status = '0'
    </update>

</mapper>
