package com.pandoli365.bibimbap.mapper;

import com.pandoli365.bibimbap.data.GameReviewData;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Options;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.SelectProvider;
import org.apache.ibatis.annotations.Update;

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

@Mapper
public interface GameReviewsMapper {

    @Select("""
            SELECT
                r.id,
                r.game_id AS gameId,
                r.user_id AS userId,
                r.rating,
                r.body,
                r.is_rating_manual AS ratingManual,
                u.display_name AS authorName,
                (r.updated_at > r.created_at) AS edited,
                r.created_at AS createdAt,
                r.updated_at AS updatedAt,
                r.deleted_at AS deletedAt
            FROM game_reviews r
            JOIN users u ON u.id = r.user_id
            WHERE r.id = #{id}
              AND r.is_delete IS NOT TRUE
              AND u.is_delete IS NOT TRUE
            """)
    GameReviewData getGameReview(long id);

    @SelectProvider(type = ReviewSqlProvider.class, method = "listReviews")
    List<GameReviewData> listGameReviews(@Param("gameId") long gameId,
                                         @Param("sort") String sort,
                                         @Param("offset") int offset,
                                         @Param("limit") int limit);

    @Select("""
            SELECT
                r.id,
                r.game_id AS gameId,
                r.user_id AS userId,
                r.rating,
                r.body,
                r.is_rating_manual AS ratingManual,
                r.created_at AS createdAt,
                r.updated_at AS updatedAt
            FROM game_reviews r
            WHERE r.game_id = #{gameId}
              AND r.user_id = #{userId}
              AND r.is_delete IS NOT TRUE
            """)
    GameReviewData getActiveReviewByGameAndUser(@Param("gameId") long gameId, @Param("userId") long userId);

    @Insert("""
            INSERT INTO game_reviews (
                game_id, user_id, rating, body, is_rating_manual
            ) VALUES (
                #{gameId}, #{userId}, #{rating}, #{body}, #{ratingManual}
            )
            """)
    @Options(useGeneratedKeys = true, keyProperty = "id", keyColumn = "id")
    int addGameReview(GameReviewData review);

    @Update("""
            UPDATE game_reviews
            SET rating = #{rating}, body = #{body},
                is_rating_manual = #{ratingManual}, updated_at = now()
            WHERE id = #{id} AND is_delete IS NOT TRUE
            """)
    int editGameReview(GameReviewData review);

    @Update("""
            UPDATE game_reviews
            SET
                is_delete = true,
                deleted_at = COALESCE(deleted_at, now())
            WHERE id = #{id}
              AND is_delete IS NOT TRUE
            """)
    int softDeleteGameReview(long id);

    class ReviewSqlProvider {

        // SELECT/JOIN/WHERE 는 컴파일타임 리터럴. ORDER BY 만 sort enum 으로 고정 문자열 분기(${} 미사용).
        public String listReviews(Map<String, Object> params) {
            String sort = (String) params.get("sort");
            String orderBy = switch (sort == null ? "" : sort) {
                case "rating_desc" -> "ORDER BY r.rating DESC, r.created_at DESC, r.id DESC";
                case "rating_asc" -> "ORDER BY r.rating ASC, r.created_at DESC, r.id DESC";
                default -> "ORDER BY r.created_at DESC, r.id DESC";
            };
            return """
                    SELECT
                        r.id,
                        r.game_id AS gameId,
                        r.user_id AS userId,
                        r.rating,
                        r.body,
                        r.is_rating_manual AS ratingManual,
                        u.display_name AS authorName,
                        (r.updated_at > r.created_at) AS edited,
                        r.created_at AS createdAt,
                        r.updated_at AS updatedAt
                    FROM game_reviews r
                    JOIN users u ON u.id = r.user_id
                    WHERE r.game_id = #{gameId}
                      AND r.is_delete IS NOT TRUE
                      AND u.is_delete IS NOT TRUE
                    """
                    + orderBy
                    + " LIMIT #{limit} OFFSET #{offset}";
        }
    }
}
