package com.zioinfo.kintex.logistics;

import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;

import java.util.List;
import java.util.Map;

/**
 * M8 반입/반출 도크 매퍼 — dock·dock_reservation. camelCase 별칭은 쌍따옴표(PG 소문자 폴딩 함정).
 */
@Mapper
public interface LogisticsMapper {

    /** 행사 배정 홀에 속한 도크 목록(그리드 행 순서). */
    @Select("""
            SELECT d.id,
                   d.dock_no AS "dockNo",
                   d.label,
                   d.heavy_priority AS "heavyPriority"
            FROM dock d
            JOIN hall_assignment ha ON ha.hall_id = d.hall_id
            WHERE ha.event_id = #{eventId}
            ORDER BY d.hall_id, d.dock_no
            """)
    List<Map<String, Object>> findDocks(@Param("eventId") String eventId);

    /** 방향/일자 기준 예약 목록. */
    @Select("""
            SELECT id,
                   dock_id AS "dockId",
                   start_hour AS "startHour",
                   span,
                   company_name AS "companyName",
                   vehicle_weight AS "vehicleWeight",
                   tone
            FROM dock_reservation
            WHERE event_id = #{eventId}
              AND direction = #{direction}
              AND reserve_date = CAST(#{date} AS date)
            ORDER BY dock_id, start_hour
            """)
    List<Map<String, Object>> findReservations(@Param("eventId") String eventId,
                                               @Param("direction") String direction,
                                               @Param("date") String date);

    /** 방향 기준 최근 예약 일자(조회 기본값 해소). 없으면 null. */
    @Select("""
            SELECT to_char(min(reserve_date), 'YYYY-MM-DD')
            FROM dock_reservation
            WHERE event_id = #{eventId} AND direction = #{direction}
            """)
    String findDefaultDate(@Param("eventId") String eventId, @Param("direction") String direction);

    /** 같은 도크·일자·방향에서 [startHour, endHour) 와 겹치는 예약 수(0=충돌 없음). */
    @Select("""
            SELECT count(*)
            FROM dock_reservation
            WHERE event_id = #{eventId}
              AND dock_id = #{dockId}
              AND direction = #{direction}
              AND reserve_date = CAST(#{date} AS date)
              AND start_hour < #{endHour}
              AND (start_hour + span) > #{startHour}
            """)
    int countOverlaps(@Param("eventId") String eventId,
                      @Param("dockId") String dockId,
                      @Param("direction") String direction,
                      @Param("date") String date,
                      @Param("startHour") int startHour,
                      @Param("endHour") int endHour);

    /** 일자 기준(방향 무관) 예약 점유 — 대기열 예측 집계용. */
    @Select("""
            SELECT start_hour AS "startHour", span
            FROM dock_reservation
            WHERE event_id = #{eventId} AND reserve_date = CAST(#{date} AS date)
            """)
    List<Map<String, Object>> findOccupancyByDate(@Param("eventId") String eventId,
                                                   @Param("date") String date);

    @Insert("""
            INSERT INTO dock_reservation
              (id, event_id, dock_id, direction, reserve_date, start_hour, span,
               company_name, vehicle_no, vehicle_weight, item, forklift, tone)
            VALUES
              (#{id}, #{eventId}, #{dockId}, #{direction}, CAST(#{date} AS date), #{startHour}, #{span},
               #{companyName}, #{vehicleNo}, #{vehicleWeight}, #{item}, #{forklift}, #{tone})
            """)
    int insertReservation(Map<String, Object> p);

    @Select("""
            SELECT id,
                   dock_id AS "dockId",
                   start_hour AS "startHour",
                   span,
                   company_name AS "companyName",
                   vehicle_weight AS "vehicleWeight",
                   tone
            FROM dock_reservation
            WHERE id = #{id}
            """)
    Map<String, Object> findReservationById(@Param("id") String id);
}
