//
//  MatchSetupView.swift
//  PadelClub
//
//  Created by Razmig Sarkissian on 23/03/2024.
//

import SwiftUI
import LeStorage

struct MatchSetupView: View {
    static let confirmationMessage = "Au moins une tête de série a été placée dans la branche de ce match dans les tours précédents. En plaçant une équipe ici, les équipes déjà placées dans la même branche seront retirées du tableau et devront être replacées."

    @EnvironmentObject var dataStore: DataStore

    @State var match: Match
    @State private var seedGroup: SeedInterval?
    
    var tournamentStore: TournamentStore? {
        return match.tournamentStore
    }
    
    var matchTypeContext: MatchType {
        match.matchType
    }
    
    @ViewBuilder
    var body: some View {
        ForEach(TeamPosition.allCases) { teamPosition in
            _teamView(inTeamPosition: teamPosition)
        }
    }
    
    @ViewBuilder
    func _teamView(inTeamPosition teamPosition: TeamPosition) -> some View {
        let scores = match.teamScores
        let team = scores.isEmpty ? nil : match.team(teamPosition)
        let teamScore = (team != nil) ? scores.first(where: { $0.teamRegistration == team!.id }) : nil
        let walkOutSpot = teamScore?.walkOut == 1
        
        let shouldConfirm = match.previousMatch(teamPosition)?.isSeeded() == true

        if let team, teamScore?.walkOut == nil {
            VStack(alignment: .leading, spacing: 0) {
                if let teamScore, teamScore.luckyLoser != nil, match.isLoserBracket == false {
                    Text("Repêchée").italic().font(.caption)
                }
                Menu {
                    _removeTeam(team: team, teamPosition: teamPosition)
                } label: {
                    TeamRowView(team: team, teamPosition: teamPosition)
                }
                .buttonStyle(.plain)
                .swipeActions(edge: .trailing, allowsFullSwipe: false) {
                    _removeTeam(team: team, teamPosition: teamPosition)
                }
            }
        } else {
            VStack(alignment: .leading) {
                if let team {
                    TeamRowView(team: team, teamPosition: teamPosition)
                        .strikethrough()
                }
                HStack {
                    let luckyLosers = walkOutSpot ? match.luckyLosers() : []
                    TeamPickerView(shouldConfirm: shouldConfirm, round: match.roundObject, matchTypeContext: matchTypeContext, luckyLosers: luckyLosers, teamPicked: { team in
                        print(team.pasteData())
                        if walkOutSpot || team.bracketPosition != nil || matchTypeContext == .loserBracket {
                            match.setLuckyLoser(team: team, teamPosition: teamPosition)
                            do {
                                try tournamentStore?.matches.addOrUpdate(instance: match)
                            } catch {
                                Logger.error(error)
                            }
                        } else if team.bracketPosition == nil {
                            team.setSeedPosition(inSpot: match, slot: teamPosition, opposingSeeding: false)
                            do {
                                try tournamentStore?.matches.addOrUpdate(instance: match)
                            } catch {
                                Logger.error(error)
                            }
                            do {
                                try tournamentStore?.teamRegistrations.addOrUpdate(instance: team)
                            } catch {
                                Logger.error(error)
                            }
                        }
                    })
                    .environment(match)
                    if matchTypeContext == .bracket, let tournament = match.currentTournament() {
                        let availableQualifiedTeams = tournament.availableQualifiedTeams()
                        let availableSeedGroups = tournament.availableSeedGroups()
                        Text("ou")
                        Menu {
                            if walkOutSpot, luckyLosers.isEmpty == false {
                                Button {
                                    if let randomTeam = luckyLosers.randomElement() {
                                        match.setLuckyLoser(team: randomTeam, teamPosition: teamPosition)
                                        do {
                                            try tournamentStore?.matches.addOrUpdate(instance: match)
                                        } catch {
                                            Logger.error(error)
                                        }
                                    }
                                } label: {
                                    Label("Repêchage", systemImage: "dice")
                                }
                            }
                            
                            if availableQualifiedTeams.isEmpty == false {
                                ConfirmButtonView(shouldConfirm: shouldConfirm, message: MatchSetupView.confirmationMessage) {
                                    if let randomTeam = availableQualifiedTeams.randomElement() {
                                        randomTeam.setSeedPosition(inSpot: match, slot: teamPosition, opposingSeeding: false)
                                        do {
                                            try tournamentStore?.matches.addOrUpdate(instance: match)
                                        } catch {
                                            Logger.error(error)
                                        }
                                        do {
                                            try tournamentStore?.teamRegistrations.addOrUpdate(instance: randomTeam)
                                        } catch {
                                            Logger.error(error)
                                        }
                                    }
                                } label: {
                                    Label("Qualifié sortant", systemImage: "dice")
                                }
                            }
                            
                            ForEach(availableSeedGroups, id: \.self) { seedGroup in
                                ConfirmButtonView(shouldConfirm: shouldConfirm, message: MatchSetupView.confirmationMessage) {
                                    if let randomTeam = tournament.randomSeed(fromSeedGroup: seedGroup) {
                                        randomTeam.setSeedPosition(inSpot: match, slot: teamPosition, opposingSeeding: false)
                                        do {
                                            try tournamentStore?.matches.addOrUpdate(instance: match)
                                        } catch {
                                            Logger.error(error)
                                        }
                                        do {
                                            try tournamentStore?.teamRegistrations.addOrUpdate(instance: randomTeam)
                                        } catch {
                                            Logger.error(error)
                                        }
                                    }
                                } label: {
                                    Label(seedGroup.localizedInterval(), systemImage: "dice")
                                }
                            }
                            
                            Divider()
                            
                            Menu {
                                ForEach(tournament.availableSeedGroups(includeAll: true), id: \.self) { seedGroup in
                                    ConfirmButtonView(shouldConfirm: shouldConfirm, message: MatchSetupView.confirmationMessage) {
                                        if let randomTeam = tournament.randomSeed(fromSeedGroup: seedGroup) {
                                            randomTeam.setSeedPosition(inSpot: match, slot: teamPosition, opposingSeeding: false)
                                            do {
                                                try tournamentStore?.matches.addOrUpdate(instance: match)
                                            } catch {
                                                Logger.error(error)
                                            }
                                            do {
                                                try tournamentStore?.teamRegistrations.addOrUpdate(instance: randomTeam)
                                            } catch {
                                                Logger.error(error)
                                            }
                                        }
                                    } label: {
                                        Label(seedGroup.localizedInterval(), systemImage: "dice")
                                    }
                                }
                            } label: {
                                Text("plus d'options")
                            }

                        } label: {
                            Text("Tirer au sort").tag(nil as SeedInterval?)
                                .underline()
                        }
                        .disabled(availableSeedGroups.isEmpty && walkOutSpot == false && availableQualifiedTeams.isEmpty)
                        
                        if matchTypeContext == .bracket {
                            Spacer()
                            if match.isSeedLocked(atTeamPosition: teamPosition) {
                                Button {
                                    match.unlockSeedPosition(atTeamPosition: teamPosition)
                                    do {
                                        try tournamentStore?.matches.addOrUpdate(instance: match)
                                    } catch {
                                        Logger.error(error)
                                    }
                                } label: {
                                    Text("Libérer")
                                        .underline()
                                }
                            } else if match.isFromLastRound() == false {
                                ConfirmButtonView(shouldConfirm: shouldConfirm, message: MatchSetupView.confirmationMessage) {
                                    _ = match.lockAndGetSeedPosition(atTeamPosition: teamPosition)
                                    do {
                                        try tournamentStore?.matches.addOrUpdate(instance: match)
                                    } catch {
                                        Logger.error(error)
                                    }
                                } label: {
                                    Text("Réserver")
                                        .underline()
                                }
                            }
                        }
                    }
                }
                .fixedSize(horizontal: false, vertical: true)
                .buttonStyle(.borderless)
            }
        }
    }
    
    func _removeTeam(team: TeamRegistration, teamPosition: TeamPosition) -> some View {
        Button(role: .cancel) {
            if match.isSeededBy(team: team, inTeamPosition: teamPosition) {
                if let score = match.teamScore(ofTeam: team) {
                    do {
                        try tournamentStore?.teamScores.delete(instance: score)
                    } catch {
                        Logger.error(error)
                    }
                }
                
                team.bracketPosition = nil
                do {
                    try tournamentStore?.teamRegistrations.addOrUpdate(instance: team)
                } catch {
                    Logger.error(error)
                }
                if let previousMatch = match.previousMatch(teamPosition) {
                    if previousMatch.disabled {
                        previousMatch.enableMatch()
                        do {
                            try tournamentStore?.matches.addOrUpdate(instance: previousMatch)
                        } catch {
                            Logger.error(error)
                        }
                    }
                }
                
                do {
                    try tournamentStore?.matches.addOrUpdate(instance: match)
                } catch {
                    Logger.error(error)
                }
            } else if match.isLoserBracket {
                if let score = match.teamScore(ofTeam: team) {
                    do {
                        try tournamentStore?.teamScores.delete(instance: score)
                    } catch {
                        Logger.error(error)
                    }
                }
            } else {
                match.teamWillBeWalkOut(team)
                do {
                    try tournamentStore?.matches.addOrUpdate(instance: match)
                } catch {
                    Logger.error(error)
                }
            }
        } label: {
            Label("retirer", systemImage: "xmark")
        }
    }
}

//#Preview {
//    MatchSetupView(match: Match.mock())
//        .environmentObject(DataStore.shared)
//}
