package com.alttd.altitudeweb.database.litebans;

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

import java.util.Arrays;
import java.util.UUID;
import java.util.stream.Collectors;

public interface HistoryCountMapper {
    /**
     * Gets the total count of punishments from all LiteBans tables.
     *
     * @return A PunishmentCount object containing counts from each table
     */
    @Select({"""
            SELECT
            (SELECT COUNT(*) FROM litebans_bans) AS bans,
            (SELECT COUNT(*) FROM litebans_mutes) AS mutes,
            (SELECT COUNT(*) FROM litebans_warnings) AS warnings,
            (SELECT COUNT(*) FROM litebans_kicks) AS kicks
            """
    })
    HistoryCount getPunishmentCounts();

    @Select("""
            SELECT COUNT(*)
            FROM (SELECT punishment.uuid, user_lookup.name AS punished_name
                  FROM all_punishments AS punishment
                           JOIN user_lookup ON user_lookup.uuid = punishment.uuid
                  WHERE user_lookup.name LIKE #{partialName}
                    AND type IN (${typeList})) AS punishment
            """)
    Integer getPlayerNamePunishmentCount(@Param("typeList") String typeList,
                                         @Param("partialName") String partialName);

    @Select("""
            SELECT COUNT(*) AS punishment_count
            FROM (SELECT uuid, banned_by_name
                  FROM all_punishments
                  WHERE banned_by_name LIKE #{partialName}
                    AND type IN (${typeList})) AS punishment
            """)
    Integer getStaffNamePunishmentCount(@Param("typeList") String typeList,
                                        @Param("partialName") String partialName);

    default Integer getNamePunishmentCount(HistoryType historyTypeEnum, UserType userTypeEnum, String partialName) {
        final String searchName = partialName.toLowerCase().replace("_", "\\_") + "%";
        String[] historyType = getHistoryType(historyTypeEnum);
        String historyTypeSqlList = Arrays.stream(historyType)
                .map(type -> "'" + type + "'")
                .collect(Collectors.joining(", "));
        return switch (userTypeEnum) {
            case PLAYER -> getPlayerNamePunishmentCount(historyTypeSqlList, searchName);
            case STAFF -> getStaffNamePunishmentCount(historyTypeSqlList, searchName);
        };
    }

    @Select("""
            SELECT COUNT(*) AS punishment_count
            FROM all_punishments
            WHERE uuid = #{uuid}
                AND type IN (${typeList})
            """)
    Integer getPlayerUuidPunishmentCount(@Param("typeList") String typeList,
                                         @Param("uuid") String uuid);

    @Select("""
            SELECT COUNT(*) AS punishment_count
            FROM all_punishments
            WHERE banned_by_uuid = #{uuid}
                AND type IN (${typeList})
            """)
    Integer getStaffUuidPunishmentCount(@Param("typeList") String typeList,
                                        @Param("uuid") String uuid);

    default Integer getUuidPunishmentCount(HistoryType historyTypeEnum, UserType userTypeEnum, UUID uuid) {
        String[] historyType = getHistoryType(historyTypeEnum);
        String historyTypeSqlList = Arrays.stream(historyType)
                .map(type -> "'" + type + "'")
                .collect(Collectors.joining(", "));
        return switch (userTypeEnum) {
            case PLAYER -> getPlayerUuidPunishmentCount(historyTypeSqlList, uuid.toString());
            case STAFF -> getStaffUuidPunishmentCount(historyTypeSqlList, uuid.toString());
        };
    }

    private String[] getHistoryType(HistoryType historyTypeEnum) {
        return switch (historyTypeEnum) {
            case ALL -> new String[]{"ban", "mute", "warn"};
            case BAN -> new String[]{"ban"};
            case MUTE -> new String[]{"mute"};
            case KICK -> new String[]{"kick"};
            case WARN -> new String[]{"warn"};
        };
    }
}
