package com.zioinfo.kintex.session;

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 org.apache.ibatis.annotations.Update;

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

/**
 * F-B4 세션 정원 RSVP + F-C5 대기열 매퍼. tenant_id='KINTEX' 고정.
 * <p>★ camelCase 별칭 쌍따옴표. ★ 확정 좌석 증가는 조건부 UPDATE(오버부킹 원자 차단).
 */
@Mapper
public interface SessionMapper {

    /**
     * 행사 세션 목록 + 내 RSVP 상태(userId null 이면 myStatus null). remaining/full 은 서버 계산.
     */
    @Select("""
            SELECT s.id,
                   s.title,
                   s.speaker,
                   s.room,
                   s.track,
                   to_char(s.starts_at, 'YYYY-MM-DD"T"HH24:MI:SS') AS "startsAt",
                   to_char(s.ends_at,   'YYYY-MM-DD"T"HH24:MI:SS') AS "endsAt",
                   s.capacity,
                   s.seat_taken AS "seatTaken",
                   CASE WHEN s.capacity = 0 THEN NULL ELSE (s.capacity - s.seat_taken) END AS "remaining",
                   CASE WHEN s.capacity > 0 AND s.seat_taken >= s.capacity THEN true ELSE false END AS "full",
                   s.status,
                   r.status AS "myStatus"
            FROM event_session s
            LEFT JOIN session_rsvp r
                   ON r.session_id = s.id AND r.user_id = #{userId} AND r.status <> 'CANCELLED'
            WHERE s.tenant_id = 'KINTEX' AND s.event_id = #{eventId}
            ORDER BY s.sort_order, s.starts_at
            """)
    List<Map<String, Object>> listSessions(@Param("eventId") String eventId, @Param("userId") String userId);

    /** 단일 세션(RSVP 검증). 없으면 null. */
    @Select("""
            SELECT id, event_id AS "eventId", title, capacity, seat_taken AS "seatTaken", status
            FROM event_session
            WHERE tenant_id = 'KINTEX' AND id = #{sessionId}
            """)
    Map<String, Object> findSession(@Param("sessionId") String sessionId);

    /** 조건부 좌석 확보 — 정원 무제한(0) 또는 여유 있을 때만 +1. 갱신행수 1이면 확보. */
    @Update("""
            UPDATE event_session
            SET seat_taken = seat_taken + 1
            WHERE tenant_id = 'KINTEX' AND id = #{sessionId} AND status = 'open'
              AND (capacity = 0 OR seat_taken < capacity)
            """)
    int takeSeat(@Param("sessionId") String sessionId);

    /** 좌석 반환(취소/승격 재계산). */
    @Update("""
            UPDATE event_session
            SET seat_taken = GREATEST(0, seat_taken - 1)
            WHERE tenant_id = 'KINTEX' AND id = #{sessionId}
            """)
    void releaseSeat(@Param("sessionId") String sessionId);

    /** 내 RSVP(세션·사용자). 없으면 null. */
    @Select("""
            SELECT id, session_id AS "sessionId", status, waitlist_pos AS "waitlistPos"
            FROM session_rsvp
            WHERE tenant_id = 'KINTEX' AND session_id = #{sessionId} AND user_id = #{userId}
            """)
    Map<String, Object> findRsvp(@Param("sessionId") String sessionId, @Param("userId") String userId);

    @Insert("""
            INSERT INTO session_rsvp (tenant_id, id, session_id, event_id, user_id, status, waitlist_pos)
            VALUES ('KINTEX', #{id}, #{sessionId}, #{eventId}, #{userId}, #{status}, #{waitlistPos})
            """)
    void insertRsvp(Map<String, Object> row);

    @Update("""
            UPDATE session_rsvp
            SET status = #{status}, waitlist_pos = #{waitlistPos}, updated_at = now()
            WHERE tenant_id = 'KINTEX' AND id = #{id}
            """)
    void updateRsvp(@Param("id") String id, @Param("status") String status,
                    @Param("waitlistPos") Integer waitlistPos);

    /** 다음 대기자(최소 순번). 없으면 null. */
    @Select("""
            SELECT id, user_id AS "userId"
            FROM session_rsvp
            WHERE tenant_id = 'KINTEX' AND session_id = #{sessionId} AND status = 'WAITLIST'
            ORDER BY waitlist_pos ASC, created_at ASC
            LIMIT 1
            """)
    Map<String, Object> findNextWaitlist(@Param("sessionId") String sessionId);

    /** 현재 최대 대기 순번(신규 대기 순번 부여). 없으면 0. */
    @Select("""
            SELECT COALESCE(MAX(waitlist_pos), 0)
            FROM session_rsvp
            WHERE tenant_id = 'KINTEX' AND session_id = #{sessionId} AND status = 'WAITLIST'
            """)
    int maxWaitlistPos(@Param("sessionId") String sessionId);

    /** 내 RSVP 목록(진행 중 우선). */
    @Select("""
            SELECT r.id,
                   r.session_id AS "sessionId",
                   r.status,
                   r.waitlist_pos AS "waitlistPos",
                   s.title,
                   s.room,
                   s.track,
                   to_char(s.starts_at, 'YYYY-MM-DD"T"HH24:MI:SS') AS "startsAt"
            FROM session_rsvp r
            JOIN event_session s ON s.id = r.session_id
            WHERE r.tenant_id = 'KINTEX' AND r.user_id = #{userId} AND r.status <> 'CANCELLED'
            ORDER BY s.starts_at
            """)
    List<Map<String, Object>> myRsvps(@Param("userId") String userId);
}
