//
//  BracketCallingView.swift
//  PadelClub
//
//  Created by razmig on 15/10/2024.
//

import SwiftUI
import LeStorage

struct BracketCallingView: View {
    @EnvironmentObject var dataStore: DataStore
    @Environment(Tournament.self) var tournament: Tournament
    @State private var initialSeedRound: Int = 0
    @State private var initialSeedCount: Int = 0
    let tournamentRounds: [Round]
    let teams: [TeamRegistration]
    
    init(tournament: Tournament) {
        let rounds = tournament.rounds()
        self.tournamentRounds = rounds
        self.teams = tournament.availableSeeds()
        if tournament.initialSeedRound == 0, rounds.count > 0 {
            let index = rounds.count - 1
            _initialSeedRound = .init(wrappedValue: index)
            _initialSeedCount = .init(wrappedValue: RoundRule.numberOfMatches(forRoundIndex: index))
        } else if tournament.initialSeedRound < rounds.count {
            _initialSeedRound = .init(wrappedValue: tournament.initialSeedRound)
            _initialSeedCount = .init(wrappedValue: tournament.initialSeedCount)
        } else if rounds.count > 0  {
            let index = rounds.count - 1
            _initialSeedRound = .init(wrappedValue: index)
            _initialSeedCount = .init(wrappedValue: RoundRule.numberOfMatches(forRoundIndex: index))
        }
    }
    
    var initialRound: Round {
        tournamentRounds.first(where: { $0.index == initialSeedRound })!
    }
    
    func filteredRounds() -> [Round] {
        tournamentRounds.filter({ $0.index >= initialSeedRound }).reversed()
    }
    
    func seedCount(forRoundIndex roundIndex: Int) -> Int {
        if roundIndex < initialSeedRound { return 0 }
        if roundIndex == initialSeedRound {
            return initialSeedCount
        }
        
        let seedCount = RoundRule.numberOfMatches(forRoundIndex: roundIndex)
        let previousSeedCount = self.seedCount(forRoundIndex: roundIndex - 1)
        
        let total = seedCount - previousSeedCount
        if total < 0 { return 0 }
        return total
    }
    
    func seeds(forRoundIndex roundIndex: Int) -> [TeamRegistration] {
        let previousSeeds: Int = (initialSeedRound..<roundIndex).map { seedCount(forRoundIndex: $0) }.reduce(0, +)
        
        
        if roundIndex == tournamentRounds.count - 1 {
            return Array(teams.dropFirst(previousSeeds))
        } else {
            return Array(teams.dropFirst(previousSeeds).prefix(seedCount(forRoundIndex: roundIndex)))
        }
    }
    
    
    var body: some View {
        List {
            let uncalledTeams = teams.filter({ $0.callDate == nil })
            if uncalledTeams.isEmpty == false {
                NavigationLink {
                    TeamsCallingView(teams: uncalledTeams)
                        .environment(tournament)
                } label: {
                    LabeledContent("Équipe\(uncalledTeams.count.pluralSuffix) non contactée\(uncalledTeams.count.pluralSuffix)", value: uncalledTeams.count.formatted())
                }
            }

            PlayersWithoutContactView(players: teams.flatMap({ $0.unsortedPlayers() }).sorted(by: \.computedRank))

            Section {
                Picker(selection: $initialSeedRound) {
                    ForEach(tournamentRounds) {
                        Text($0.roundTitle()).tag($0.index)
                    }
                } label: {
                    Text("Premier tour")
                }
                .onChange(of: initialSeedRound) {
                    initialSeedCount = RoundRule.numberOfMatches(forRoundIndex: initialSeedRound)
                }

                LabeledContent {
                    StepperView(count: $initialSeedCount, minimum: 0, maximum: RoundRule.numberOfMatches(forRoundIndex: initialSeedRound))
                } label: {
                    Text("Têtes de série")
                }
            } footer: {
                Text("Permet de convoquer par tour du tableau sans avoir tirer au sort les tétes de série. Vous pourrez ensuite confirmer leur horaire plus précis si le tour se joue sur plusieurs rotations. Les équipes ne peuvent pas être considéré comme convoqué au bon horaire en dehors de cet écran tant qu'elles n'ont pas été placé dans le tableau.")
            }
            
            ForEach(filteredRounds()) { round in
                let seeds = seeds(forRoundIndex: round.index)
                let startDate = round.startDate ?? round.playedMatches().first?.startDate
                let callSeeds = seeds.filter({ tournament.isStartDateIsDifferentThanCallDate($0, expectedSummonDate: startDate) == false })
                if seeds.isEmpty == false {
                    Section {
                        NavigationLink {
                            _roundView(round: round, seeds: seeds)
                                .environment(tournament)
                        } label: {
                            CallView.CallStatusView(count: callSeeds.count, total: seeds.count, startDate: startDate, title: "convoquées")
                        }
                    } header: {
                        Text(round.roundTitle())
                    } footer: {
                        if let startDate {
                            CallView(teams: seeds, callDate: startDate, matchFormat: round.matchFormat, roundLabel: round.roundTitle())
                        }
                    }
                }
            }
        }
        .onDisappear(perform: {
            tournament.initialSeedCount = initialSeedCount
            tournament.initialSeedRound = initialSeedRound
            _save()
        })
        .headerProminence(.increased)
        .navigationTitle("Pré-convocation")
    }
    
    private func _save() {
        do {
            try dataStore.tournaments.addOrUpdate(instance: tournament)
        } catch {
            Logger.error(error)
        }
    }

    @ViewBuilder
    private func _roundView(round: Round, seeds: [TeamRegistration]) -> some View {
        List {
            
            let uncalledTeams = seeds.filter({ $0.callDate == nil })
            if uncalledTeams.isEmpty == false {
                NavigationLink {
                    TeamsCallingView(teams: uncalledTeams)
                        .environment(tournament)
                } label: {
                    LabeledContent("Équipe\(uncalledTeams.count.pluralSuffix) non contactée\(uncalledTeams.count.pluralSuffix)", value: uncalledTeams.count.formatted())
                }
            }
            
            let startDate = round.startDate ?? round.playedMatches().first?.startDate
            let badCalled = seeds.filter({ tournament.isStartDateIsDifferentThanCallDate($0, expectedSummonDate: startDate) })
            
            if badCalled.isEmpty == false {
                Section {
                    ForEach(badCalled) { team in
                        TeamCallView(team: team)
                    }
                } header: {
                    HStack {
                        Text("Mauvais horaire")
                        Spacer()
                        Text(badCalled.count.formatted() + " équipe\(badCalled.count.pluralSuffix)")
                    }
                } footer: {
                    if let startDate {
                        CallView(teams: badCalled, callDate: startDate, matchFormat: round.matchFormat, roundLabel: round.roundTitle())
                    }
                }
            }

            Section {
                ForEach(seeds) { team in
                    TeamCallView(team: team)
                }
            } header: {
                HStack {
                    Text(round.roundTitle())
                    Spacer()
                    Text(seeds.count.formatted() + " équipe\(seeds.count.pluralSuffix)")
                }
            }
        }
        .overlay {
            if seeds.isEmpty {
                ContentUnavailableView {
                    Label("Aucune équipe dans ce tour", systemImage: "clock.badge.questionmark")
                } description: {
                    Text("Padel Club n'a pas réussi à déterminer quelles équipes jouent ce tour.")
                } actions: {
//                    RowButtonView("Horaire intelligent") {
//                        selectedScheduleDestination = nil
//                    }
                }
            }
        }
        .headerProminence(.increased)
        .navigationTitle(round.roundTitle())
        .navigationBarTitleDisplayMode(.inline)
        .toolbarBackground(.visible, for: .navigationBar)
    }
}

//#Preview {
//    SeedsCallingView()
//}
