//
//  GroupStagesSettingsView.swift
//  PadelClub
//
//  Created by Razmig Sarkissian on 31/03/2024.
//

import SwiftUI
import LeStorage

struct GroupStagesSettingsView: View {
    @EnvironmentObject var dataStore: DataStore
    @Environment(\.dismiss) private var dismiss
    @Environment(Tournament.self) var tournament: Tournament
    @State private var generationDoneMessage: String?
    let step: Int
    
    var tournamentStore: TournamentStore? {
        return self.tournament.tournamentStore
    }
    
    var body: some View {
        List {
            if tournament.shouldVerifyGroupStage {
                Section {
                    let issues = tournament.groupStageTeamPlacementIssue()
                    DisclosureGroup {
                        ForEach(issues.shouldBeInIt, id: \.self) { id in
                            if let team: TeamRegistration = self.tournamentStore?.teamRegistrations.findById(id) {
                                TeamRowView(team: team)
                            }
                        }
                    } label: {
                        LabeledContent {
                            Text(issues.shouldBeInIt.count.formatted())
                        } label: {
                            Text("Équipes à mettre en poule")
                        }
                    }
                    DisclosureGroup {
                        ForEach(issues.shouldNotBeInIt, id: \.self) { id in
                            if let team = self.tournamentStore?.teamRegistrations.findById(id) {
                                Menu {
                                    Button("Retirer de sa poule") {
                                        team.resetGroupeStagePosition()
                                        do {
                                            try self.tournamentStore?.teamRegistrations.addOrUpdate(instance: team)
                                        } catch {
                                            Logger.error(error)
                                        }
                                    }
                                } label: {
                                    TeamRowView(team: team)
                                }
                            }
                        }
                    } label: {
                        LabeledContent {
                            Text(issues.shouldNotBeInIt.count.formatted())
                        } label: {
                            Text("Équipes à retirer des poules")
                        }
                    }
                    RowButtonView("Valider les poules en l'état", role: .destructive) {
                        tournament.shouldVerifyGroupStage = false
                        do {
                            try dataStore.tournaments.addOrUpdate(instance: tournament)
                        } catch {
                            Logger.error(error)
                        }
                    }
                } footer: {
                    Text("Suite à un changement dans votre liste d'inscrits, veuillez vérifier l'intégrité de vos poules et valider que tout est ok.")
                }
            }
            
            Section {
                if tournament.groupStageLoserBracket() == nil {
                    RowButtonView("Ajouter des matchs de classements", role: .destructive) {
                        let round = Round(tournament: tournament.id, index: 0, matchFormat: tournament.loserRoundFormat, groupStageLoserBracket: true)
                        
                        do {
                            try tournamentStore?.rounds.addOrUpdate(instance: round)
                        } catch {
                            Logger.error(error)
                        }

                    }
                } else if let groupStageLoserBracket = tournament.groupStageLoserBracket() {
                    RowButtonView("Supprimer les matchs de classements", role: .destructive) {
                        do {
                            try tournamentStore?.rounds.delete(instance: groupStageLoserBracket)
                        } catch {
                            Logger.error(error)
                        }
                    }
                }
            }
            
            if tournament.lastStep() == 0, step == 0 {
                Section {
                    RowButtonView("Ajouter une phase de poule", role: .destructive) {
                        tournament.addNewGroupStageStep()
                    }
                } footer: {
                    Text("Padel Club peut vous créer une 2ème phase de poule utilisant les résultats de la première phase : les premiers de chaque poule joueront ensemble et ainsi de suite.")
                }
            } else if step > 0 {
                Section {
                    RowButtonView("Supprimer cette phase de poule", role: .destructive) {
                        let groupStages = tournament.groupStages(atStep: tournament.lastStep())
                        do {
                            try self.tournamentStore?.groupStages.delete(contentOfs: groupStages)
                        } catch {
                            Logger.error(error)
                        }
                        
                        dismiss()
                    }
                }

            }
                        
            #if DEBUG
            Section {
                RowButtonView("delete all group stages") {
                    tournament.deleteGroupStages()
                }
            }
            #endif

            Section {
                menuGenerateGroupStage(.random)
            } footer: {
                Text("Redistribue les équipes par tirage au sort par chapeau")
            }
            
            Section {
                menuGenerateGroupStage(.snake)
            } footer: {
                Text("Redistribue les équipes par la méthode du serpentin")
            }
            
            Section {
                RowButtonView("Retirer tous les horaires", role: .destructive) {
                    let matches = tournament.groupStages().flatMap({ $0._matches() })
                    tournament.groupStages().flatMap({ $0._matches() }).forEach { match in
                        match.startDate = nil
                        match.endDate = nil
                    }
                    
                    do {
                        try tournamentStore?.matches.addOrUpdate(contentOfs: matches)
                    } catch {
                        Logger.error(error)
                    }
                }
            } footer: {
                Text("Retire les horaires pré-définis des matchs. Utile si vous avez convoqué mais que l'ordre des matchs à lancer n'est pas important.").foregroundStyle(.logoRed).bold()
            }
            
            if tournament.unsortedTeams().filter({ $0.groupStagePosition != nil }).isEmpty == false {
                Section {
                    menuBuildAllGroupStages
                } footer: {
                    Text("Efface et recréé les poules, les horaires et les résultats existants seront perdus").foregroundStyle(.logoRed).bold()
                }
            }
            
            let groupStages = tournament.groupStages()

            Section {
                if groupStages.anySatisfy({ $0.isReturnMatchEnabled() }) {
                    RowButtonView("Effacer les matchs retours", role: .destructive) {
                        groupStages.filter({ $0.isReturnMatchEnabled() }).forEach { groupStage in
                            groupStage.removeReturnMatches()
                        }
                        generationDoneMessage = "Matchs retours effacés"
                    }
                }
                
            }
            
            Section {
                if groupStages.anySatisfy({ $0.isReturnMatchEnabled() == false }) {
                    RowButtonView("Rajouter les matchs retours", role: .destructive) {
                        groupStages.filter({ $0.isReturnMatchEnabled() == false }).forEach { groupStage in
                            groupStage.addReturnMatches()
                        }
                        
                        generationDoneMessage = "Matchs retours créés"
                    }
                } else if groupStages.allSatisfy({ $0.isReturnMatchEnabled() }) {
                    RowButtonView("Rajouter une vague de matchs", role: .destructive) {
                        groupStages.forEach { groupStage in
                            groupStage.addReturnMatches()
                        }
                        
                        generationDoneMessage = "Nouveaux matchs créés"
                    }
                }
            }

            Section {
                RowButtonView("Nommer les poules alphabétiquement", role: .destructive) {
                    let groupStages = tournament.groupStages()
                    groupStages.forEach { groupStage in
                        if let letter = Alphabet.letterForIndex(index: groupStage.index) {
                            groupStage.name = "Poule " + letter
                        }
                    }
                    do {
                        try self.tournament.tournamentStore?.groupStages.addOrUpdate(contentOfs: groupStages)
                    } catch {
                        Logger.error(error)
                    }
                }
            }
            
            Section {
                RowButtonView("Supprimer les noms des poules", role: .destructive) {
                    let groupStages = tournament.groupStages()
                    groupStages.forEach { groupStage in
                        groupStage.name = nil
                    }
                    do {
                        try self.tournament.tournamentStore?.groupStages.addOrUpdate(contentOfs: groupStages)
                    } catch {
                        Logger.error(error)
                    }
                }
            }
            
            Section {
                RowButtonView("Retirer tout le monde", role: .destructive) {
                    tournament.groupStages().forEach { groupStage in
                        let teams = groupStage.teams()
                        teams.forEach { team in
                            team.groupStagePosition = nil
                            team.groupStage = nil
                            groupStage._matches().forEach({ $0.updateTeamScores() })
                        }
                        do {
                            try tournamentStore?.teamRegistrations.addOrUpdate(contentOfs: teams)
                        } catch {
                            Logger.error(error)
                        }
                    }
                }
            } footer: {
                Text("Toutes les équipes seront retirées et les scores des matchs seront perdus.")
            }

        }
        .overlay(alignment: .bottom) {
            if let generationDoneMessage {
                Label(generationDoneMessage, systemImage: "checkmark.circle.fill")
                    .toastFormatted()
                    .deferredRendering(for: .seconds(2))
            }
        }
        .toolbar {
            ToolbarItem(placement: .topBarTrailing) {
                ShareLink(item: groupStagesPaste(), preview: .init("Données des poules"))
            }
        }
    }
    
    func groupStagesPaste() -> TournamentGroupStageShareContent {
        TournamentGroupStageShareContent(tournament: tournament)
    }
    
    
    var menuBuildAllGroupStages: some View {
        RowButtonView("Refaire les poules", role: .destructive) {
            tournament.deleteGroupStages()
            tournament.buildGroupStages()
            generationDoneMessage = "Poules mises à jour"
            tournament.shouldVerifyGroupStage = false
            _save()
        }
    }

    @ViewBuilder
    func menuGenerateGroupStage(_ mode: GroupStageOrderingMode) -> some View {
        RowButtonView("Poule \(mode.localizedLabel().lowercased())", role: .destructive, systemImage: mode.systemImage) {
            tournament.groupStageOrderingMode = mode
            tournament.refreshGroupStages(keepExistingMatches: true)
            generationDoneMessage = "Poules mises à jour"
            tournament.shouldVerifyGroupStage = false
            _save()
        }
    }
    
    private func _save() {
        do {
            try dataStore.tournaments.addOrUpdate(instance: tournament)
        } catch {
            Logger.error(error)
        }
    }
}

//#Preview {
//    GroupStageSettingsView()
//        .environment(Tournament.mock())
//}
