//
//  TournamentRankView.swift
//  PadelClub
//
//  Created by Razmig Sarkissian on 30/04/2024.
//

import SwiftUI
import LeStorage

struct TournamentRankView: View {
    @Environment(Tournament.self) var tournament: Tournament
    @EnvironmentObject var dataStore: DataStore
    
    @State private var rankings: [Int: [TeamRegistration]] = [:]
    @State private var calculating = false
    @State private var selectedTeam: TeamRegistration?

    var isEditingTeam: Binding<Bool> {
        Binding {
            selectedTeam != nil
        } set: { value in
        }
    }
    
    var body: some View {
        List {
            @Bindable var tournament = tournament
            let matchs = tournament.runningMatches(tournament.allMatches())
            let rankingPublished = tournament.selectedSortedTeams().allSatisfy({ $0.finalRanking != nil })
            Section {
                LabeledContent {
                    Text(matchs.count.formatted())
                } label: {
                    Text("Matchs en cours")
                }

                LabeledContent {
                    if rankingPublished {
                        Image(systemName: "checkmark")
                            .foregroundStyle(.green)
                    } else {
                        Image(systemName: "xmark")
                            .foregroundStyle(.logoRed)
                    }
                } label: {
                    Text("Classement publié")
                }
                
                Toggle(isOn: $tournament.hidePointsEarned) {
                    Text("Masquer les points gagnés")
                }
                .onChange(of: tournament.hidePointsEarned) {
                    do {
                        try dataStore.tournaments.addOrUpdate(instance: tournament)
                    } catch {
                        Logger.error(error)
                    }
                }

                if rankingPublished == false {
                    RowButtonView("Publier le classement", role: .destructive) {
                        _publishRankings()
                    }
                } else {
                    RowButtonView("Re-publier le classement", role: .destructive) {
                        _publishRankings()
                    }
                }
            }
            
            if rankingPublished {
                Section {
                    RowButtonView("Supprimer le classement", role: .destructive) {
                        tournament.unsortedTeams().forEach { team in
                            team.finalRanking = nil
                            team.pointsEarned = nil
                        }
                        _save()
                    }
                } footer: {
                    Text(.init("Masque également le classement sur le site [Padel Club](\(URLs.main.rawValue))"))
                }
            }
            
            if rankingPublished {
                Section {
                    ForEach(tournament.teamsRanked()) { team in
                        let key = team.finalRanking ?? 0
                        Button {
                            selectedTeam = team
                        } label: {
                            TeamRankCellView(team: team, key: key)
                                .frame(maxWidth: .infinity)
                        }
                        .contentShape(Rectangle())
                        .buttonStyle(.plain)
                    }
                } footer: {
                    Text("Vous pouvez appuyer sur une ligne pour éditer manuellement le classement calculé par Padel Club.")
                }
            } else {
                let keys = rankings.keys.sorted()
                ForEach(keys, id: \.self) { key in
                    if let rankedTeams = rankings[key] {
                        ForEach(rankedTeams) { team in
                            TeamRankCellView(team: team, key: key)
                        }
                    }
                }
            }
        }
        .alert("Position", isPresented: isEditingTeam) {
            if let selectedTeam {
                @Bindable var team = selectedTeam
                TextField("Position", value: $team.finalRanking, format: .number)
                    .keyboardType(.numberPad)
                    .multilineTextAlignment(.trailing)
                    .frame(maxWidth: .infinity)
                
                Button("Valider") {
                    selectedTeam.pointsEarned = tournament.isAnimation() ? nil : tournament.tournamentLevel.points(for: selectedTeam.finalRanking! - 1, count: tournament.teamCount)
                    do {
                        try dataStore.teamRegistrations.addOrUpdate(instance: selectedTeam)
                    } catch {
                        Logger.error(error)
                    }

                    self.selectedTeam = nil
                }

                Button("Annuler", role: .cancel) {
                    self.selectedTeam = nil
                }
            }
        }
        .overlay(content: {
            if calculating {
                ProgressView()
            }
        })
        .onAppear {
            let rankingPublished = tournament.selectedSortedTeams().allSatisfy({ $0.finalRanking != nil })
            if rankingPublished == false {
                calculating = true
                Task {
                    await _calculateRankings()
                    calculating = false
                }
            }
        }
        .navigationTitle("Classement")
        .navigationBarTitleDisplayMode(.inline)
        .toolbarBackground(.visible, for: .navigationBar)
        .toolbar {
            ToolbarItem(placement: .topBarTrailing) {
                if let url = tournament.shareURL(.rankings) {
                    _actionForURL(url)
                }
            }
        }
    }
    
    struct TeamRankCellView: View {
        @Environment(Tournament.self) var tournament: Tournament
        let team: TeamRegistration
        let key: Int
        
        var body: some View {
            HStack {
                VStack(alignment: .trailing) {
                    VStack(alignment: .trailing, spacing: -8.0) {
                        ZStack(alignment: .trailing) {
                            Text(tournament.teamCount.formatted()).hidden()
                            Text(key.formatted())
                        }
                        .monospacedDigit()
                        .font(.largeTitle)
                        .fontWeight(.bold)
                        Text(key.ordinalFormattedSuffix()).font(.caption)
                    }
                    if let index = tournament.indexOf(team: team) {
                        let rankingDifference = index - (key - 1)
                        if rankingDifference > 0 {
                            HStack(spacing: 0.0) {
                                Text(rankingDifference.formatted(.number.sign(strategy: .always())))
                                    .monospacedDigit()
                                Image(systemName: "arrowtriangle.up.fill")
                                    .imageScale(.small)
                            }
                            .foregroundColor(.green)
                        } else if rankingDifference < 0 {
                            HStack(spacing: 0.0) {
                                Text(rankingDifference.formatted(.number.sign(strategy: .always())))
                                    .monospacedDigit()
                                Image(systemName: "arrowtriangle.down.fill")
                                    .imageScale(.small)
                            }
                            .foregroundColor(.red)
                        } else {
                            Text("--")
                        }
                    }
                }
                
                
                Divider()
                
                VStack(alignment: .leading) {
                    if let name = team.name {
                        Text(name).foregroundStyle(.secondary)
                    }
                    
                    ForEach(team.players()) { player in
                        VStack(alignment: .leading, spacing: -4.0) {
                            Text(player.playerLabel()).bold()
                            HStack(alignment: .firstTextBaseline, spacing: 0.0) {
                                Text(player.rankLabel())
                                if let rank = player.getRank() {
                                    Text(rank.ordinalFormattedSuffix())
                                        .font(.caption)
                                }
                            }
                        }
                    }
                }
                
                if tournament.isAnimation() == false && key > 0 {
                    Spacer()
                    VStack(alignment: .trailing) {
                        HStack(alignment: .lastTextBaseline, spacing: 0.0) {
                            Text(tournament.tournamentLevel.points(for: key - 1, count: tournament.teamCount).formatted(.number.sign(strategy: .always())))
                            Text("pts").font(.caption)
                        }
                    }
                }
            }
        }
    }
    
    private func _publishRankings() {
        rankings.keys.sorted().forEach { rank in
            if let rankedTeams = rankings[rank] {
                rankedTeams.forEach { team in
                    team.finalRanking = rank
                    team.pointsEarned = tournament.isAnimation() ? nil : tournament.tournamentLevel.points(for: rank - 1, count: tournament.teamCount)
                }
            }
        }
        _save()
    }
    
    private func _calculateRankings() async {
        let finalRanks = await tournament.finalRanking()
        finalRanks.keys.sorted().forEach { rank in
            if let rankedTeamIds = finalRanks[rank] {
                rankings[rank] = rankedTeamIds.compactMap { Store.main.findById($0) }
            }
        }
    }
    
    @ViewBuilder
    private func _actionForURL(_ url: URL, removeSource: Bool = false) -> some View {
        Menu {
            Button {
                UIApplication.shared.open(url)
            } label: {
                Label("Voir", systemImage: "safari")
            }
            
            ShareLink(item: url) {
                Label("Partager le lien", systemImage: "link")
            }
        } label: {
            Image(systemName: "square.and.arrow.up")
        }
        .frame(maxWidth: .infinity)
        .buttonStyle(.borderless)
    }

    
    private func _save() {
        do {
            try dataStore.teamRegistrations.addOrUpdate(contentOfs: tournament.unsortedTeams())
        } catch {
            Logger.error(error)
        }
    }
}

//#Preview {
//    TournamentRankView()
//}
