package com.pandoli365.bibimbap.mapper;

import com.pandoli365.bibimbap.data.JamData;
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.Update;

import java.time.OffsetDateTime;
import java.util.List;

@Mapper
public interface JamsMapper {

    @Select("""
            SELECT id, slug, title, description, status,
                   recruit_start_at AS recruitStartAt,
                   dev_start_at AS devStartAt,
                   eval_start_at AS evalStartAt,
                   eval_end_at AS evalEndAt,
                   discord_url AS discordUrl,
                   prize_info AS prizeInfo,
                   sponsor_info AS sponsorInfo,
                   is_visible AS isVisible,
                   created_by AS createdBy,
                   created_at AS createdAt,
                   updated_at AS updatedAt,
                   is_delete AS isDelete
            FROM jams
            WHERE id = #{jamId}
              AND is_delete IS NOT TRUE
            """)
    JamData getById(long jamId);

    @Select("""
            SELECT id, slug, title, description, status,
                   recruit_start_at AS recruitStartAt,
                   dev_start_at AS devStartAt,
                   eval_start_at AS evalStartAt,
                   eval_end_at AS evalEndAt,
                   discord_url AS discordUrl,
                   prize_info AS prizeInfo,
                   sponsor_info AS sponsorInfo,
                   is_visible AS isVisible,
                   created_by AS createdBy,
                   created_at AS createdAt,
                   updated_at AS updatedAt,
                   is_delete AS isDelete
            FROM jams
            WHERE slug = #{slug}
              AND is_delete IS NOT TRUE
            """)
    JamData getBySlug(String slug);

    @Select("""
            <script>
            SELECT id, slug, title, description, status,
                   recruit_start_at AS recruitStartAt,
                   dev_start_at AS devStartAt,
                   eval_start_at AS evalStartAt,
                   eval_end_at AS evalEndAt,
                   discord_url AS discordUrl,
                   prize_info AS prizeInfo,
                   sponsor_info AS sponsorInfo,
                   is_visible AS isVisible,
                   created_by AS createdBy,
                   created_at AS createdAt,
                   updated_at AS updatedAt,
                   is_delete AS isDelete
            FROM jams
            WHERE is_visible IS NOT FALSE
              AND is_delete IS NOT TRUE
            <if test="cursorCreatedAt != null and cursorId != null">
              AND (created_at, id) &lt; (#{cursorCreatedAt}, #{cursorId})
            </if>
            ORDER BY created_at DESC, id DESC
            LIMIT #{limit}
            </script>
            """)
    List<JamData> listVisibleKeyset(@Param("cursorCreatedAt") OffsetDateTime cursorCreatedAt,
                                    @Param("cursorId") Long cursorId,
                                    @Param("limit") int limit);

    @Select("""
            SELECT id, slug, title, description, status,
                   recruit_start_at AS recruitStartAt,
                   dev_start_at AS devStartAt,
                   eval_start_at AS evalStartAt,
                   eval_end_at AS evalEndAt,
                   discord_url AS discordUrl,
                   prize_info AS prizeInfo,
                   sponsor_info AS sponsorInfo,
                   is_visible AS isVisible,
                   created_by AS createdBy,
                   created_at AS createdAt,
                   updated_at AS updatedAt,
                   is_delete AS isDelete
            FROM jams
            WHERE is_delete IS NOT TRUE
            ORDER BY created_at DESC, id DESC
            """)
    List<JamData> listAllForAdmin();

    @Insert("""
            INSERT INTO jams (
                slug,
                title,
                description,
                status,
                recruit_start_at,
                dev_start_at,
                eval_start_at,
                eval_end_at,
                discord_url,
                prize_info,
                sponsor_info,
                is_visible,
                created_by
            ) VALUES (
                #{slug},
                #{title},
                #{description},
                #{status},
                #{recruitStartAt},
                #{devStartAt},
                #{evalStartAt},
                #{evalEndAt},
                #{discordUrl},
                #{prizeInfo},
                #{sponsorInfo},
                #{isVisible},
                #{createdBy}
            )
            """)
    @Options(useGeneratedKeys = true, keyProperty = "id", keyColumn = "id")
    int insertJam(JamData jam);

    @Update("""
            UPDATE jams SET
                title = #{title},
                description = #{description},
                recruit_start_at = #{recruitStartAt},
                dev_start_at = #{devStartAt},
                eval_start_at = #{evalStartAt},
                eval_end_at = #{evalEndAt},
                discord_url = #{discordUrl},
                prize_info = #{prizeInfo},
                sponsor_info = #{sponsorInfo},
                is_visible = #{isVisible},
                updated_at = now()
            WHERE id = #{id}
              AND is_delete IS NOT TRUE
            """)
    int updateJam(JamData jam);

    @Update("""
            UPDATE jams SET
                status = #{status},
                updated_at = now()
            WHERE id = #{jamId}
              AND is_delete IS NOT TRUE
            """)
    int updateStatus(@Param("jamId") long jamId, @Param("status") String status);

    @Update("""
            UPDATE jams SET
                is_visible = #{isVisible},
                updated_at = now()
            WHERE id = #{jamId}
              AND is_delete IS NOT TRUE
            """)
    int updateVisibility(@Param("jamId") long jamId, @Param("isVisible") boolean isVisible);

    @Update("""
            UPDATE jams SET
                is_delete = true,
                updated_at = now()
            WHERE id = #{jamId}
              AND is_delete IS NOT TRUE
            """)
    int softDelete(long jamId);

    @Select("""
            SELECT id, slug, title, description, status,
                   recruit_start_at AS recruitStartAt,
                   dev_start_at AS devStartAt,
                   eval_start_at AS evalStartAt,
                   eval_end_at AS evalEndAt,
                   discord_url AS discordUrl,
                   prize_info AS prizeInfo,
                   sponsor_info AS sponsorInfo,
                   is_visible AS isVisible,
                   created_by AS createdBy,
                   created_at AS createdAt,
                   updated_at AS updatedAt,
                   is_delete AS isDelete
            FROM jams
            WHERE status IN ('RECRUIT', 'DEV', 'EVAL')
              AND is_visible IS NOT FALSE
              AND is_delete IS NOT TRUE
            ORDER BY created_at DESC, id DESC
            LIMIT #{limit}
            """)
    List<JamData> listActive(@Param("limit") int limit);

    @Select("""
            SELECT COUNT(*)
            FROM jams
            WHERE status IN ('RECRUIT', 'DEV', 'EVAL')
              AND is_visible IS NOT FALSE
              AND is_delete IS NOT TRUE
            """)
    int countActive();
}
