/*
 *   This file is a part of the SteamWar software.
 *
 *   Copyright (C) 2025 SteamWar.de-Serverteam
 *
 *   This program is free software: you can redistribute it and/or modify
 *   it under the terms of the GNU Affero General Public License as published by
 *   the Free Software Foundation, either version 3 of the License, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 *   GNU Affero General Public License for more details.
 *
 *   You should have received a copy of the GNU Affero General Public License
 *   along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */

package de.steamwar.sql

import de.steamwar.sql.internal.useDb
import org.jetbrains.exposed.v1.core.IntegerColumnType
import org.jetbrains.exposed.v1.core.VarCharColumnType
import org.jetbrains.exposed.v1.core.dao.id.CompositeID
import org.jetbrains.exposed.v1.core.dao.id.CompositeIdTable
import org.jetbrains.exposed.v1.core.dao.id.EntityID
import org.jetbrains.exposed.v1.core.eq
import org.jetbrains.exposed.v1.core.inList
import org.jetbrains.exposed.v1.dao.CompositeEntity
import org.jetbrains.exposed.v1.dao.CompositeEntityClass
import org.jetbrains.exposed.v1.jdbc.insertIgnore

object FightPlayerTable : CompositeIdTable("FightPlayer") {
    val fightId = reference("FightId", FightTable)
    val userId = reference("UserId", SteamwarUserTable).index()
    val team = integer("Team")
    val kit = varchar("Kit", 64)
    val kills = integer("Kills")
    val out = bool("IsOut")

    init {
        addIdColumn(fightId)
        addIdColumn(userId)
    }
}

class FightPlayer(id: EntityID<CompositeID>) : CompositeEntity(id) {
    companion object : CompositeEntityClass<FightPlayer>(FightPlayerTable) {
        @JvmStatic
        fun create(
            fightId: Int,
            userId: Int,
            blue: Boolean,
            kit: String,
            kills: Int,
            out: Boolean
        ) =
            useDb {
                FightPlayerTable.insertIgnore {
                    it[this.fightId] = fightId
                    it[this.userId] = userId
                    it[this.team] = if (blue) 1 else 2
                    it[this.kit] = kit
                    it[this.kills] = kills
                    it[this.out] = out
                }
            }

        @JvmStatic
        fun batchGet(fightIds: List<Int>) =
            useDb {
                find { FightPlayerTable.fightId inList fightIds.toList() }.toList()
            }

        @JvmStatic
        fun countFights(userId: Int) =
            useDb {
                find { FightPlayerTable.userId eq userId }.count()
            }

        @JvmStatic
        fun countFights(userId: Int, type: String) =
            useDb {
                exec(
                    "SELECT COUNT(*) AS FightCount FROM FightPlayer INNER JOIN Fight F on FightPlayer.FightID = F.FightID WHERE UserID = ? AND GameMode LIKE ?",
                    args = listOf(IntegerColumnType() to userId, VarCharColumnType() to "$type%")
                ) {
                    if (it.next()) {
                        it.getInt("FightCount")
                    } else {
                        0
                    }
                }
                    ?: 0
            }
    }

    val fightID by FightPlayerTable.fightId.transform({ EntityID(it, FightTable) }, { it.value })
    val userID by FightPlayerTable.userId.transform({ EntityID(it, SteamwarUserTable) }, { it.value })
    val team by FightPlayerTable.team
    val kit by FightPlayerTable.kit
    val kills by FightPlayerTable.kills
    val out by FightPlayerTable.out

    fun isOut() =
        out
}