package de.tsschulz.tt_tagebuch.app.ui

import de.tsschulz.tt_tagebuch.shared.api.models.ClubTeamDto
import de.tsschulz.tt_tagebuch.shared.api.models.Member
import java.util.Calendar
import java.util.GregorianCalendar

/**
 * Zuordnungen Spieler ↔ Mannschaft in der Saison-Planung (Halbserie),
 * analog `planningAssignments` / `normalizePlanningTeamAssignments` in `TeamManagementView.vue`.
 */
internal data class PlanningAssignment(
    val teamId: Int,
    val memberId: Int,
    val position: Int,
)

internal object TeamPlanningLogic {

    fun defaultLineupHalf(): String =
        if (isSecondHalfSeason()) "second_half" else "first_half"

    private fun isSecondHalfSeason(): Boolean {
        val now = GregorianCalendar()
        val seasonStart = GregorianCalendar(now.get(Calendar.YEAR), Calendar.JULY, 1, 0, 0, 0)
        if (seasonStart.after(now)) {
            seasonStart.add(Calendar.YEAR, -1)
        }
        val secondHalfStart = GregorianCalendar(seasonStart.get(Calendar.YEAR) + 1, Calendar.JANUARY, 1, 0, 0, 0)
        return now.timeInMillis >= secondHalfStart.timeInMillis
    }

    fun normalizeAssignments(raw: List<PlanningAssignment>): List<PlanningAssignment> {
        val filtered = raw.filter { it.teamId > 0 && it.memberId > 0 }
        val byTeam = filtered.groupBy { it.teamId }
        val out = ArrayList<PlanningAssignment>()
        byTeam.entries.sortedBy { it.key }.forEach { (_, entries) ->
            entries
                .sortedBy { it.position }
                .forEachIndexed { idx, e ->
                    out.add(PlanningAssignment(teamId = e.teamId, memberId = e.memberId, position = idx + 1))
                }
        }
        return out
    }

    fun withoutMember(assignments: List<PlanningAssignment>, memberId: Int): List<PlanningAssignment> =
        assignments.filter { it.memberId != memberId }

    fun assignToTeamEnd(
        assignments: List<PlanningAssignment>,
        teamId: Int,
        memberId: Int,
    ): List<PlanningAssignment> {
        val without = withoutMember(assignments, memberId)
        val teamCount = without.count { it.teamId == teamId }
        return without + PlanningAssignment(teamId = teamId, memberId = memberId, position = teamCount + 1)
    }

    fun removeFromTeam(assignments: List<PlanningAssignment>, teamId: Int, memberId: Int): List<PlanningAssignment> {
        val without = assignments.filterNot { it.teamId == teamId && it.memberId == memberId }
        return normalizeAssignments(without)
    }

    fun moveWithinTeam(
        assignments: List<PlanningAssignment>,
        teamId: Int,
        memberId: Int,
        direction: Int,
    ): List<PlanningAssignment>? {
        val teamEntries = assignments.filter { it.teamId == teamId }.sortedBy { it.position }
        val index = teamEntries.indexOfFirst { it.memberId == memberId }
        if (index < 0) return null
        val target = index + direction
        if (target < 0 || target >= teamEntries.size) return null
        val reordered = teamEntries.toMutableList()
        val tmp = reordered[index]
        reordered[index] = reordered[target]
        reordered[target] = tmp
        val others = assignments.filter { it.teamId != teamId }
        val updated = others + reordered.mapIndexed { idx, e ->
            PlanningAssignment(teamId = teamId, memberId = e.memberId, position = idx + 1)
        }
        return normalizeAssignments(updated)
    }

    fun teamLineupMembers(assignments: List<PlanningAssignment>, teamId: Int, membersById: Map<Int, Member>): List<Member> =
        assignments
            .filter { it.teamId == teamId }
            .sortedBy { it.position }
            .mapNotNull { membersById[it.memberId] }

    fun isEligible(member: Member, team: ClubTeamDto, seasonLabel: String): Boolean {
        val tAge = TeamEditorLineupLogic.configuredTeamAgeGroup(team.teamAgeGroup, team.league?.name)
        val tGender = TeamEditorLineupLogic.configuredTeamGender(team.teamGender, team.league?.name)
        return TeamEditorLineupLogic.isEligibleForTeam(member, tAge, tGender, seasonLabel)
    }

    fun lineupGapOk(membersOrdered: List<Member>, template: (String, String) -> String): String? =
        TeamEditorLineupLogic.lineupGapViolationMessage(membersOrdered, template)
}
