//
//  EditScoreView.swift
//  Padel Tournament
//
//  Created by Razmig Sarkissian on 27/02/2023.
//

import SwiftUI
import LeStorage

struct EditScoreView: View {

    @EnvironmentObject var dataStore: DataStore
    
    @StateObject var matchDescriptor: MatchDescriptor
    @State private var presentMatchFormatSelection: Bool = false
    @Binding var confirmScoreEdition: Bool
    @Environment(\.dismiss) private var dismiss
    @State private var firstTeamIsFirstScoreToEnter: Bool = true
    @State private var shouldEndMatch: Bool = false

    init(match: Match, confirmScoreEdition: Binding<Bool>) {
        let matchDescriptor = MatchDescriptor(match: match)
        _matchDescriptor = .init(wrappedValue: matchDescriptor)
        _confirmScoreEdition = confirmScoreEdition
        _shouldEndMatch = .init(wrappedValue: matchDescriptor.hasEnded)
    }
        
    var defaultTeamIsActive: Bool {
        if firstTeamIsFirstScoreToEnter {
            matchDescriptor.teamOneSetupIsActive
        } else {
            matchDescriptor.teamTwoSetupIsActive
        }
    }
    
    var otherTeamIsActive: Bool {
        if firstTeamIsFirstScoreToEnter {
            matchDescriptor.teamTwoSetupIsActive
        } else {
            matchDescriptor.teamOneSetupIsActive
        }
    }

    func walkout(_ team: TeamPosition) {
        self.matchDescriptor.match?.setWalkOut(team)
        save()
        dismiss()
    }
    
    func pointRange(winner: Bool) -> Int? {
        guard let match = matchDescriptor.match else { return nil }
        guard let tournament = match.currentTournament() else {
            return nil
        }
            
        let teamsCount = tournament.teamCount
        guard let round = match.roundObject else { return nil }
        
        guard let seedInterval = round.seedInterval(), match.index == 0 else {
            return nil
        }
        
        return winner ? tournament.tournamentLevel.points(for: seedInterval.first - 1, count: teamsCount) : tournament.tournamentLevel.points(for: seedInterval.last - 1, count: teamsCount)
    }
    
    func getColor(setDescriptor: SetDescriptor) -> Color {
        switch (firstTeamIsFirstScoreToEnter, setDescriptor.isTeamOneSet == false) {
        case (true, true), (false, false):
            return matchDescriptor.colorTeamOne
        default:
            return matchDescriptor.colorTeamTwo
        }
    }
    
    func teamScorePositionLabel(teamPosition: TeamPosition) -> String {
        switch (firstTeamIsFirstScoreToEnter, teamPosition == .one) {
        case (true, true), (false, false):
            return "score de gauche"
        default:
            return "score de droite"
        }
    }
    
    var body: some View {
        Form {
            Section {
                HStack {
                    VStack(alignment: .leading) {
                        Text(teamScorePositionLabel(teamPosition: .one)).font(.caption)
                        Text(matchDescriptor.teamLabelOne)
                        if matchDescriptor.hasEnded, let pointRange = pointRange(winner: matchDescriptor.winner == .one) {
                            Text(pointRange.formatted(.number.sign(strategy: .always())) + " pts")
                                .bold()
                        }
                    }
                    Spacer()
                }
                .listRowView(isActive: defaultTeamIsActive, color: matchDescriptor.colorTeamOne, hideColorVariation: false)
                .contentShape(Rectangle())
                .frame(maxWidth: .infinity)
                .onTapGesture {
                    firstTeamIsFirstScoreToEnter.toggle()
                }
                HStack {
                    Spacer()
                    VStack(alignment: .trailing) {
                        Text(teamScorePositionLabel(teamPosition: .two)).font(.caption)
                        Text(matchDescriptor.teamLabelTwo).multilineTextAlignment(.trailing)
                        if matchDescriptor.hasEnded, let pointRange = pointRange(winner: matchDescriptor.winner == .two) {
                            Text(pointRange.formatted(.number.sign(strategy: .always())) + " pts")
                                .bold()
                        }
                    }
                }
                .listRowView(isActive: otherTeamIsActive, color: matchDescriptor.colorTeamTwo, hideColorVariation: false, alignment: .trailing)
                .contentShape(Rectangle())
                .frame(maxWidth: .infinity)
                .onTapGesture {
                    firstTeamIsFirstScoreToEnter.toggle()
                }
            } header: {
                if let roundTitle = matchDescriptor.match?.roundAndMatchTitle() {
                    Text(roundTitle)
                }
            } footer: {
                HStack {
                    Menu {
                        Button {
                            walkout(.one)
                        } label: {
                            Text(matchDescriptor.teamLabelOne)
                        }
                        Button {
                            walkout(.two)
                        } label: {
                            Text(matchDescriptor.teamLabelTwo)
                        }
                        
                        Divider()
                        
                        Button {
                            self.matchDescriptor.match?.removeWalkOut()
                            save()
                        } label: {
                            Text("Annuler un forfait")
                        }
                    } label: {
                        Text("Forfait d'une équipe ?")
                            .underline()
                    }
                    Spacer()

                    FooterButtonView("Format : \(matchDescriptor.matchFormat.shortFormat)") {
                        presentMatchFormatSelection = true
                    }
                }
            }
            ForEach($matchDescriptor.setDescriptors) { $setDescriptor in
                SetInputView(setDescriptor: $setDescriptor, firstTeamIsFirstScoreToEnter: firstTeamIsFirstScoreToEnter)
                    .onChange(of: setDescriptor.hasEnded) {
                        if setDescriptor.hasEnded {
                            if matchDescriptor.hasEnded == false {
                                matchDescriptor.addNewSet()
                            }
                        } else {
                            let index = matchDescriptor.setDescriptors.firstIndex(where: { $0 == setDescriptor }) ?? 0
                            matchDescriptor.setDescriptors = Array(matchDescriptor.setDescriptors[0...index])
                        }
                    }
                    .tint(getColor(setDescriptor: setDescriptor))
            }
            
            if matchDescriptor.hasEnded {
                Section {
                    HStack {
                        Spacer()
                        VStack {
                            Text(matchDescriptor.winnerLabel)
                        }
                        .multilineTextAlignment(.center)
                        Spacer()
                    }
                    RowButtonView("Victoire") {
                        matchDescriptor.match?.setScore(fromMatchDescriptor: matchDescriptor)
                        save()
                        dismiss()
                    }
                } footer: {
                    Text("Termine la rencontre sur ce score")
                }
            } else if matchDescriptor.match?.hasEnded() == false {
                Section {
                    Toggle(isOn: $shouldEndMatch) {
                        Text("Terminer le match")
                    }
                    
                    RowButtonView("Confirmer") {
                        if shouldEndMatch {
                            matchDescriptor.match?.setUnfinishedScore(fromMatchDescriptor: matchDescriptor)
                        } else {
                            matchDescriptor.match?.updateScore(fromMatchDescriptor: matchDescriptor)
                        }
                        save()
                        dismiss()
                    }
                } footer: {
                    if shouldEndMatch {
                        Text("Le match n'a pas pu aboutir.")
                    } else {
                        Text("Met à jour le score, ne termine pas la rencontre")
                    }
                }
            }
        }
        .sheet(isPresented: $presentMatchFormatSelection) {
            MatchFormatSelectionView(matchFormat: $matchDescriptor.matchFormat, additionalEstimationDuration: matchDescriptor.match?.currentTournament()?.additionalEstimationDuration)
                .tint(.master)
        }
        .onChange(of: matchDescriptor.matchFormat) {
            presentMatchFormatSelection = false
            matchDescriptor.setDescriptors.removeAll()
            matchDescriptor.addNewSet()
        }
    }
    
    func save() {
        self.confirmScoreEdition = true
        if let match = matchDescriptor.match {
            do {
                try match.tournamentStore?.matches.addOrUpdate(instance: match)
            } catch {
                Logger.error(error)
            }
        }
    }
}
