//
//  RoundView.swift
//  PadelClub
//
//  Created by Razmig Sarkissian on 30/03/2024.
//

import SwiftUI
import LeStorage
import TipKit

struct RoundView: View {
    @Environment(\.isEditingTournamentSeed) private var isEditingTournamentSeed
    @Environment(Tournament.self) var tournament: Tournament
    @EnvironmentObject var dataStore: DataStore
    @Environment(NavigationViewModel.self) private var navigation: NavigationViewModel

    @State private var selectedSeedGroup: SeedInterval?
    @State private var spaceLeft: [Match] = []
    @State private var seedSpaceLeft: [Match] = []
    @State private var availableSeedGroup: SeedInterval?
    @State private var showPrintScreen: Bool = false
    
    var round: Round
    
    private func _getAvailableSeedGroup() async {
        availableSeedGroup = tournament.seedGroupAvailable(atRoundIndex: round.index)
    }
    
    private func _getSpaceLeft() async {
        self.spaceLeft.removeAll()
        self.seedSpaceLeft.removeAll()
        let displayableMatches: [Match] = self.round.displayableMatches()
        displayableMatches.forEach { match in
            let count: Int = match.teamScores.count
            if count == 0 {
                seedSpaceLeft.append(match)
            } else if count == 1 {
                spaceLeft.append(match)
            }
        }
    }
    
    var showVisualDrawView: Binding<Bool> { Binding(
        get: { selectedSeedGroup != nil },
        set: {
            if $0 == false {
                selectedSeedGroup = nil
            }
        }
    )}

    var body: some View {
        List {
            let displayableMatches = round.displayableMatches().sorted(by: \.index)
            let loserRounds = round.loserRounds()
            if displayableMatches.isEmpty {
                Section {
                    ContentUnavailableView("Aucun match dans cette manche", systemImage: "tennisball")
                }
            } else if isEditingTournamentSeed.wrappedValue == false {
                //(where: { $0.isDisabled() == false || isEditingTournamentSeed.wrappedValue })
                let printTip = PrintTip()
                TipView(printTip) { actions in
                    showPrintScreen = true
                }
                .tipStyle(tint: .master, asSection: true)

                if loserRounds.isEmpty == false {
                    let correspondingLoserRoundTitle = round.correspondingLoserRoundTitle()
                    Section {
                        NavigationLink {
                            LoserRoundsView(upperBracketRound: round)
                                .environment(tournament)
                                .navigationTitle(correspondingLoserRoundTitle)
                        } label: {
                            Text(correspondingLoserRoundTitle)
                        }
                    }
                }
            } else {
                let disabledMatchesCount = BracketEditTip.matchesHidden
                if disabledMatchesCount > 0 {
                    let bracketTip = BracketEditTip(nextRoundName: round.nextRound()?.roundTitle())
                    TipView(bracketTip).tipStyle(tint: .green, asSection: true)
                    
                    Section {
                        let leftToPlay = (RoundRule.numberOfMatches(forRoundIndex: round.index) - disabledMatchesCount)
                        LabeledContent {
                            Text(leftToPlay.formatted()).font(.largeTitle)
                        } label: {
                            Text("Match\(leftToPlay.pluralSuffix) à jouer \(round.roundTitle(.short))")
                            Text("\(disabledMatchesCount) match\(disabledMatchesCount.pluralSuffix) désactivé\(disabledMatchesCount.pluralSuffix) automatiquement")
                        }
                    }
                }
                
                let availableSeeds = tournament.availableSeeds()
                let availableQualifiedTeams = tournament.availableQualifiedTeams()

                if availableSeeds.isEmpty == false, let availableSeedGroup {
                    Section {
                        RowButtonView("Placer \(availableSeedGroup.localizedLabel())" + ((availableSeedGroup.isFixed() == false) ? " au hasard" : ""))  {
                            tournament.setSeeds(inRoundIndex: round.index, inSeedGroup: availableSeedGroup)
                            await _save()
                            if tournament.availableSeeds().isEmpty && tournament.availableQualifiedTeams().isEmpty {
                                self.isEditingTournamentSeed.wrappedValue = false
                            }
                            await _getSpaceLeft()
                            await _getAvailableSeedGroup()
                        }
                    } footer: {
                        if availableSeedGroup.isFixed() == false {
                            Text("Le tirage au sort ne sera pas visuel. Toutes les équipes de ce chapeau seront tirées.")
                        }
                    }
                    
                    if (availableSeedGroup.isFixed() == false) {
                        Section {
                            RowButtonView("Tirage au sort \(availableSeedGroup.localizedLabel()) visuel") {
                                self.selectedSeedGroup = availableSeedGroup
                            }
                        } footer: {
                            Text("Le tirage au sort sera visuel et automatique, n'hésitez pas à enregistrer une vidéo de votre écran. Toutes les équipes de ce chapeau seront tirées les unes après les autres.")
                        }
                    }
                }

                if availableQualifiedTeams.isEmpty == false {
                    if spaceLeft.isEmpty == false {
                        Section {
                            DisclosureGroup {
                                ForEach(availableQualifiedTeams) { team in
                                    NavigationLink {
                                        SpinDrawView(drawees: [team], segments: spaceLeft) { results in
                                            Task {
                                                results.forEach { drawResult in
                                                    team.setSeedPosition(inSpot: spaceLeft[drawResult.drawIndex], slot: nil, opposingSeeding: true)
                                                }
                                                await _save()
                                                if tournament.availableSeeds().isEmpty && tournament.availableQualifiedTeams().isEmpty {
                                                    self.isEditingTournamentSeed.wrappedValue = false
                                                }
                                                await _getSpaceLeft()
                                                await _getAvailableSeedGroup()
                                            }
                                        }
                                    } label: {
                                        TeamRowView(team: team, displayCallDate: false)
                                    }
                                }
                            } label: {
                                Text("Qualifié\(availableQualifiedTeams.count.pluralSuffix) à placer").badge(availableQualifiedTeams.count)
                            }
                        } header: {
                            Text("Tirage au sort visuel d'un qualifié").font(.subheadline)
                        }
                    }
                }
                
                if availableSeeds.isEmpty == false {
                    if seedSpaceLeft.isEmpty == false {
                        Section {
                            DisclosureGroup {
                                ForEach(availableSeeds) { team in
                                    NavigationLink {
                                        SpinDrawView(drawees: [team], segments: seedSpaceLeft) { results in
                                            Task {
                                                results.forEach { drawResult in
                                                    team.setSeedPosition(inSpot: seedSpaceLeft[drawResult.drawIndex], slot: nil, opposingSeeding: false)
                                                }
                                                await _save()
                                                if tournament.availableSeeds().isEmpty && tournament.availableQualifiedTeams().isEmpty {
                                                    self.isEditingTournamentSeed.wrappedValue = false
                                                }
                                                await _getSpaceLeft()
                                                await _getAvailableSeedGroup()
                                            }
                                        }
                                    } label: {
                                        TeamRowView(team: team, displayCallDate: false)
                                    }
                                }
                            } label: {
                                Text("Tête\(availableSeeds.count.pluralSuffix) de série à placer").badge(availableSeeds.count)
                            }
                        } header: {
                            Text("Tirage au sort visuel d'une tête de série").font(.subheadline)
                        }
                    } else if spaceLeft.isEmpty == false {
                        Section {
                            DisclosureGroup {
                                ForEach(availableSeeds) { team in
                                    NavigationLink {
                                        SpinDrawView(drawees: [team], segments: spaceLeft) { results in
                                            Task {
                                                results.forEach { drawResult in
                                                    team.setSeedPosition(inSpot: spaceLeft[drawResult.drawIndex], slot: nil, opposingSeeding: true)
                                                }
                                                await _save()
                                                if tournament.availableSeeds().isEmpty && tournament.availableQualifiedTeams().isEmpty {
                                                    self.isEditingTournamentSeed.wrappedValue = false
                                                }
                                                await _getSpaceLeft()
                                                await _getAvailableSeedGroup()
                                            }
                                        }
                                    } label: {
                                        TeamRowView(team: team, displayCallDate: false)
                                    }
                                }
                            } label: {
                                Text("Tête\(availableSeeds.count.pluralSuffix) de série à placer").badge(availableSeeds.count)
                            }
                        } header: {
                            Text("Tirage au sort visuel d'une tête de série").font(.subheadline)
                        }
                    }
                }
            }

            if isEditingTournamentSeed.wrappedValue == true {
                let slideToDelete = SlideToDeleteSeedTip()
                TipView(slideToDelete).tipStyle(tint: .logoRed, asSection: true)
            }
            
            ForEach(displayableMatches) { match in
                Section {
                    MatchRowView(match: match, matchViewStyle: .sectionedStandardStyle)
                } header: {
                    HStack {
                        Text(round.roundTitle(.wide))
                        if round.index > 0 {
                            Text(match.matchTitle(.short, inMatches: displayableMatches))
                        } else {
                            let tournamentTeamCount = tournament.teamCount
                            if let seedIntervalPointRange = round.seedInterval()?.pointsRange(tournamentLevel: tournament.tournamentLevel, teamsCount: tournamentTeamCount) {
                                Spacer()
                                Text(seedIntervalPointRange)
                                    .font(.caption)
                            }
                        }
                        
                        #if DEBUG
                        Spacer()
                        
                        Text(match.teamScores.count.formatted())
                        #endif
                    }
                }
            }
        }
        .navigationDestination(isPresented: $showPrintScreen) {
            PrintSettingsView(tournament: tournament)
        }
        .onAppear {
            Task {
                await _prepareRound()
            }
            let seeds = round.seeds()
            SlideToDeleteSeedTip.seeds = seeds.count
            PrintTip.seeds = seeds.count
            BracketEditTip.matchesHidden = round.getDisabledMatches().count
        }
        .fullScreenCover(isPresented: showVisualDrawView) {
            if let availableSeedGroup = selectedSeedGroup {
                let seeds = tournament.seeds(inSeedGroup: availableSeedGroup)
                let availableSeedSpot = tournament.availableSeedSpot(inRoundIndex: round.index)
                NavigationStack {
                    SpinDrawView(drawees: seeds, segments: availableSeedSpot, autoMode: true) { draws in
                        Task {
                            draws.forEach { drawResult in
                                seeds[drawResult.drawee].setSeedPosition(inSpot: availableSeedSpot[drawResult.drawIndex], slot: nil, opposingSeeding: false)
                            }
                            await _save()
                            if tournament.availableSeeds().isEmpty && tournament.availableQualifiedTeams().isEmpty {
                                self.isEditingTournamentSeed.wrappedValue = false
                            }
                        }
                    }
                }
            }
        }
        .headerProminence(.increased)
        .toolbar {
            ToolbarItem(placement: .topBarTrailing) {
                Button(isEditingTournamentSeed.wrappedValue == true ? "Valider" : "Modifier") {
                    if isEditingTournamentSeed.wrappedValue == true {
                        Task {
                           await _save()
                        }
                    }
                    isEditingTournamentSeed.wrappedValue.toggle()
                }
            }
        }
    }
    
    private func _save() async {
        do {
            try dataStore.teamRegistrations.addOrUpdate(contentOfs: tournament.unsortedTeams())
        } catch {
            Logger.error(error)
        }
        
        //todo should be done server side
        let rounds = tournament.rounds()
        rounds.forEach { round in
            let matches = round.playedMatches()
            matches.forEach { match in
                match.name = Match.setServerTitle(upperRound: round, matchIndex: match.indexInRound(in: matches))
            }
        }
        let allRoundMatches = tournament.allRoundMatches()
        do {
            try DataStore.shared.matches.addOrUpdate(contentOfs: allRoundMatches)
        } catch {
            Logger.error(error)
        }
    }
    
    private func _prepareRound() async {
        Task {
            await _getSpaceLeft()
        }
        Task {
            await _getAvailableSeedGroup()
        }
    }
}

//#Preview {
//    RoundView(round: Round.mock())
//        .environment(Tournament.mock())
//}
