//
//  GroupStageView.swift
//  Padel Tournament
//
//  Created by Razmig Sarkissian on 02/03/2023.
//

import SwiftUI
import LeStorage

struct GroupStageView: View {
    
    @EnvironmentObject var dataStore: DataStore
    
    @Environment(Tournament.self) private var tournament
    @Bindable var groupStage: GroupStage
    @State private var confirmGroupStageStart: Bool = false
    @State private var sortingMode: GroupStageSortingMode
    
    init(groupStage: GroupStage) {
        self.groupStage = groupStage
        _sortingMode = .init(wrappedValue: groupStage.hasEnded() ? .score : .weight)
    }
    
    var tournamentStore: TournamentStore? {
        return self.tournament.tournamentStore
    }
    
    var body: some View {
        List {
            let playedMatches = groupStage.playedMatches()

            Section {
                GroupStageScoreView(groupStage: groupStage, sortByScore: sortingMode == .score)
            } header: {
                if let startDate = groupStage.startDate {
                    Text(startDate.formatted(Date.FormatStyle().weekday(.wide)).capitalized + " à partir de " +  startDate.formattedAsHourMinute())
                }
            } footer: {
                HStack {
                    Spacer()
                    Picker(selection: $sortingMode) {
                        Text("tri par score").tag(GroupStageSortingMode.score)
                        Text("tri par poids").tag(GroupStageSortingMode.weight)
                    } label: {
                        
                    }
                    .pickerStyle(.segmented)
                    .fixedSize()
                    Spacer()
                }
            }
            .headerProminence(.increased)
            .onChange(of: playedMatches) {
                if groupStage.hasEnded() {
                    sortingMode = .score
                }
            }

            let runningMatches = groupStage.runningMatches(playedMatches: playedMatches)
            Section {
                MatchListView(section: "en cours", matches: groupStage.runningMatches(playedMatches: playedMatches), hideWhenEmpty: true)
            }
            
            let availableToStart = groupStage.availableToStart(playedMatches: playedMatches, in: runningMatches)
            Section {
                MatchListView(section: "prêt à démarrer", matches: availableToStart, hideWhenEmpty: true)
                    .listRowView(isActive: availableToStart.isEmpty == false, color: .green, hideColorVariation: true)
            }
            Section {
                
                MatchListView(section: "à lancer", matches: groupStage.readyMatches(playedMatches: playedMatches), hideWhenEmpty: true)
            }
            
            Section {
                
                MatchListView(section: "terminés", matches: groupStage.finishedMatches(playedMatches: playedMatches), hideWhenEmpty: playedMatches.isEmpty || playedMatches.flatMap({ $0.teamScores }).isEmpty, isExpanded: false)
            }
            
            if playedMatches.isEmpty {
                RowButtonView("Créer les matchs de poules") {
                    groupStage.buildMatches()
                }
            } else if groupStage.step > 0, playedMatches.flatMap({ $0.teamScores }).isEmpty {
                Section {
                    RowButtonView("Préparer les matchs") {
                        playedMatches.forEach { match in
                            match.updateTeamScores()
                        }
                    }
                    .disabled(tournament.groupStagesAreOver(atStep: 0) == false)
                } footer: {
                    Text("La première phase doit être terminée avant de pouvoir préparer les matchs de la deuxième phase de poule.")
                }

            }
        }
        .toolbar {
            ToolbarItem(placement: .topBarTrailing) {
                _groupStageMenuView()
            }
        }
        .navigationTitle(groupStage.groupStageTitle(.title))
    }
    
    private enum GroupStageSortingMode {
        case score
        case weight
    }
        
    struct GroupStageScoreView: View {
        
        @EnvironmentObject var dataStore: DataStore
        @Environment(Tournament.self) private var tournament

        let groupStage: GroupStage
        let sortByScore: Bool
        let scores: [GroupStage.TeamGroupStageScore]?
        let teams: [TeamRegistration]
        
        var tournamentStore: TournamentStore? {
            return self.tournament.tournamentStore
        }
        
        init(groupStage: GroupStage, sortByScore: Bool) {
            self.groupStage = groupStage
            self.sortByScore = sortByScore
            self.scores = sortByScore ? (0..<groupStage.size).compactMap({ groupStage._score(forGroupStagePosition: $0) }) : nil
            self.teams = groupStage.teams(sortByScore, scores: scores)
        }
        
        private func _teamAt(atIndex index: Int) -> TeamRegistration? {
            sortByScore ? teams[safe: index] : groupStage.teamAt(groupStagePosition: index)
        }
        
        var body: some View {
            ForEach(0..<(groupStage.size), id: \.self) { index in
                if let team = _teamAt(atIndex: index), let groupStagePosition = team.groupStagePositionAtStep(groupStage.step) {
                    NavigationLink {
                        GroupStageTeamView(groupStage: groupStage, team: team)
                            .environment(self.tournament)
                    } label: {
                        let players = team.players()
                        VStack(alignment: .leading, spacing: 4.0) {
                            HStack(spacing: 6.0) {
                                Text("#\(groupStagePosition + 1)")
                                if players.isEmpty == false, groupStage.tournamentObject()?.hideWeight() == false {
                                    Text("Poids \(team.weight)")
                                }
                                if players.isEmpty == false, team.isWildCard() {
                                    Text("wildcard").foregroundStyle(.logoRed).font(.caption).italic()
                                }
                                Spacer()
                                if team.qualified {
                                    Text("qualifié")
                                }
                            }
                            .font(.footnote)
                            HStack {
                                VStack(alignment: .leading) {
                                    if let teamName = team.name, teamName.isEmpty == false {
                                        Text(teamName).foregroundStyle(.secondary).font(.footnote)
                                    } else if players.isEmpty {
                                        if team.isWildCard() {
                                            Text("Place réservée wildcard")
                                        } else {
                                            Text("Place réservée")
                                        }
                                    }
                                    ForEach(players) { player in
                                        Text(player.playerLabel()).lineLimit(1)
                                            .overlay {
                                                if player.hasArrived && team.isHere() == false {
                                                    Color.green.opacity(0.6)
                                                }
                                            }
                                    }
                                }
                                Spacer()
                                if let score = groupStage.scoreLabel(forGroupStagePosition: groupStagePosition, score: scores?.first(where: { $0.team.groupStagePositionAtStep(groupStage.step) == groupStagePosition })) {
                                    VStack(alignment: .trailing) {
                                        HStack(spacing: 0.0) {
                                            Text(score.wins)
                                            Text("/")
                                            Text(score.losses)
                                        }.font(.headline).monospacedDigit()
                                        if let setsDifference = score.setsDifference {
                                            HStack(spacing: 4.0) {
                                                Text(setsDifference)
                                            }.font(.footnote)
                                        }
                                        if let gamesDifference = score.gamesDifference {
                                            HStack(spacing: 4.0) {
                                                Text(gamesDifference)
                                            }.font(.footnote)
                                        }
                                    }
                                }
                            }
                        }
                        .contextMenu {
                            let teamHasArrived = team.isHere()
                            Button {
                                team.hasArrived(isHere: teamHasArrived)
                            } label: {
                                if teamHasArrived {
                                    Label("équipe présente", systemImage: "checkmark").foregroundStyle(.green)
                                } else {
                                    Text("équipe présente")
                                }
                            }

                            Divider()
                            
                            Section {
                                ForEach(team.players()) { player in
                                    Button {
                                        player.hasArrived.toggle()
                                        do {
                                            try self.tournamentStore?.playerRegistrations.addOrUpdate(instance: player)
                                        } catch {
                                            Logger.error(error)
                                        }
                                    } label: {
                                        if player.hasArrived {
                                            Label("\(player.playerLabel())", systemImage: "checkmark")
                                        } else {
                                            Text("\(player.playerLabel())")
                                        }
                                    }
                                }
                            } header: {
                                Text("Joueur présent")
                            }
                        }
                    }
                    .listRowView(isActive: team.qualified, color: .master)
                    .listRowView(isActive: team.isHere() && groupStage.hasEnded() == false, color: .green, hideColorVariation: true)
                } else {
                    VStack(alignment: .leading, spacing: 0) {
                        Text("#\(index + 1)")
                            .font(.caption)
                        TeamPickerView(groupStagePosition: index, matchTypeContext: .groupStage, teamPicked: { team in
                            print(team.pasteData())
                            team.groupStage = groupStage.id
                            team.groupStagePosition = index
                            groupStage._matches().forEach({ $0.updateTeamScores() })
                            do {
                                try tournamentStore?.teamRegistrations.addOrUpdate(instance: team)
                            } catch {
                                Logger.error(error)
                            }
                        })
                    }
                }
            }
        }
    }
    
    private func _groupStageMenuView() -> some View {
        NavigationLink {
            GroupStageSettingsView(groupStage: groupStage)
                .environment(tournament)
        } label: {
            Label {
                Text("Modifier")
            } icon: {
                Image(systemName: "gear.circle")
                    .resizable()
                    .scaledToFit()
                    .frame(height: 28)
            }
            .labelStyle(.titleOnly)
        }
    }
    
    private func _save() {
        do {
            try tournamentStore?.groupStages.addOrUpdate(instance: groupStage)
        } catch {
            Logger.error(error)
        }
    }
}
