//
//  EditingTeamView.swift
//  PadelClub
//
//  Created by Razmig Sarkissian on 17/04/2024.
//

import SwiftUI
import LeStorage

struct EditingTeamView: View {
    @EnvironmentObject var dataStore: DataStore
    @EnvironmentObject var networkMonitor: NetworkMonitor
    @Environment(Tournament.self) var tournament: Tournament
    @Environment(\.dismiss) private var dismiss

    var team: TeamRegistration
    @State private var editedTeam: TeamRegistration?
    @State private var contactType: ContactType? = nil
    @State private var sentError: ContactManagerError? = nil
    @State private var showSubscriptionView: Bool = false
    @State private var registrationDate : Date
    @State private var walkOut : Bool
    @State private var wildCardBracket : Bool
    @State private var wildCardGroupStage : Bool
    @State private var name: String
    @FocusState private var focusedField: TeamRegistration.CodingKeys?
    
    var messageSentFailed: Binding<Bool> {
        Binding {
            sentError != nil
        } set: { newValue in
            if newValue == false {
                sentError = nil
            }
        }
    }

    var hasChanged: Binding<Bool> {
        Binding {
            if canSaveWithoutWarning() {
                return false
            }
            
            return
                registrationDate != team.registrationDate
                || walkOut != team.walkOut
                || wildCardBracket != team.wildCardBracket
                || wildCardGroupStage != team.wildCardGroupStage

        } set: { _ in
        }
    }
    
    var tournamentStore: TournamentStore? {
        return self.tournament.tournamentStore
    }

    init(team: TeamRegistration) {
        self.team = team
        _name = .init(wrappedValue: team.name ?? "")
        _registrationDate = State(wrappedValue: team.registrationDate ?? Date())
        _walkOut = State(wrappedValue: team.walkOut)
        _wildCardBracket = State(wrappedValue: team.wildCardBracket)
        _wildCardGroupStage = State(wrappedValue: team.wildCardGroupStage)
    }
    
    private func _resetTeam() {
        team.resetPositions()
        team.qualified = false
        team.wildCardGroupStage = false
        team.walkOut = false
        team.wildCardBracket = false
    }
    
    var body: some View {
        List {
            Section {
                RowButtonView("Modifier la composition de l'équipe", role: team.hasRegisteredOnline() ? .destructive : .none, confirmationMessage: "Vous êtes sur le point de modifier une équipe qui s'est inscrite en ligne.") {
                    editedTeam = team
                }
                TeamDetailView(team: team)
            } header: {
                if team.hasRegisteredOnline() {
                    Text("Inscription en ligne")
                } else {
                    Text("Inscription par vous-même")
                }
            } footer: {
                HStack {
                    CopyPasteButtonView(pasteValue: team.playersPasteData())
                    Spacer()
                    NavigationLink {
                        GroupStageTeamReplacementView(team: team)
                            .environment(tournament)
                    } label: {
                        Text("Chercher à remplacer")
                            .underline()
                    }
                }
            }
            .headerProminence(.increased)
            
            Section {
                if let callDate = team.callDate {
                    LabeledContent() {
                        Text(callDate.localizedDate())
                    } label: {
                        Text("Convocation")
                    }
                    
                    Toggle(isOn: confirmationReceived) {
                        Text("Confirmation reçue")
                        Text("L'équipe vous a confirmé votre convocation")
                    }

                } else {
                    Text("Cette équipe n'a pas été convoquée")
                }

                if team.unsortedPlayers().isEmpty == false {
                    Toggle(isOn: hasArrived) {
                        Text("Équipe sur place")
                    }
                }
            }
            
            Section {
                DatePicker(selection: $registrationDate) {
                    Text("Inscription")
                    Text(registrationDate.localizedWeekDay().capitalized)
                }
                
                Toggle(isOn: $wildCardBracket) {
                    Text("Wildcard Tableau")
                }
                
                Toggle(isOn: $wildCardGroupStage) {
                    Text("Wildcard Poule")
                }.disabled(tournament.groupStageCount == 0)
                
                Toggle(isOn: $walkOut) {
                    Text("Forfait")
                }
            }
            
            Section {
                HStack {
                    TextField("Nom de l'équipe", text: $name)
                        .autocorrectionDisabled()
                        .focused($focusedField, equals: ._name)
                        .keyboardType(.alphabet)
                        .frame(maxWidth: .infinity)
                        .submitLabel(.done)
                        .onSubmit(of: .text) {
                            let trimmed = name.prefixTrimmed(200)
                            if trimmed.isEmpty {
                                team.name = nil
                            } else {
                                team.name = trimmed
                            }
                            
                            _save()
                        }
                    if name.isEmpty == false {
                        FooterButtonView("effacer", role: .destructive) {
                            name = ""
                            team.name = nil
                            _save()
                        }
                    }
                }
            } header: {
                Text("Nom de l'équipe")
            }
            
            if tournament.tournamentLevel.coachingIsAuthorized {
                CoachListView(team: team)
            }
            
            Section {
                RowButtonView("Retirer des poules", role: .destructive) {
                    team.resetGroupeStagePosition()
                    _save()
                }
                .disabled(team.inGroupStage() == false)
            }

            Section {
                RowButtonView("Retirer du tableau", role: .destructive) {
                    team.resetBracketPosition()
                    _save()
                }
                .disabled(team.inRound() == false)
            }
            
            Section {
                RowButtonView("Effacer l'équipe", role: .destructive, systemImage: "trash") {
                    _resetTeam()
                    team.deleteTeamScores()
                    do {
                        try tournamentStore?.teamRegistrations.delete(instance: team)
                    } catch {
                        Logger.error(error)
                    }
                    dismiss()
                }
            } footer: {
                if team.hasRegisteredOnline() {
                    Text("Attention, supprimer cette équipe notifiera par email que leur inscription a été annulée.").foregroundStyle(.logoRed)
                }
            }
        }
        .alert("Attention", isPresented: hasChanged, actions: {
            Button("Confirmer") {
                _resetTeam()
                team.registrationDate = registrationDate
                team.wildCardBracket = wildCardBracket
                team.wildCardGroupStage = wildCardGroupStage
                team.walkOut = walkOut
                _save()
            }
            
            Button("Annuler", role: .cancel) {
                registrationDate = team.registrationDate ?? Date()
                walkOut = team.walkOut
                wildCardBracket = team.wildCardBracket
                wildCardGroupStage = team.wildCardGroupStage
            }
        }, message: {
            Text("Ce changement peut entraîner l'entrée ou la sortie d'une équipe de votre sélection. Padel Club préviendra automatiquement une équipe inscrite en ligne de son nouveau statut.")
        })
        .navigationBarBackButtonHidden(focusedField != nil)
        .toolbar(content: {
            if focusedField != nil {
                ToolbarItem(placement: .topBarLeading) {
                    Button("Annuler", role: .cancel) {
                        focusedField = nil
                    }
                }
            }
        })
        .alert("Un problème est survenu", isPresented: messageSentFailed) {
            Button("OK") {
            }
        } message: {
            Text(_networkErrorMessage)
        }
        .sheet(item: $contactType) { contactType in
            Group {
                switch contactType {
                case .message(_, let recipients, let body, _):
                    if Guard.main.paymentForNewTournament() != nil {
                        MessageComposeView(recipients: recipients, body: body) { result in
                            switch result {
                            case .cancelled:
                                break
                            case .failed:
                                self.sentError = .messageFailed
                            case .sent:
                                if networkMonitor.connected == false {
                                    self.contactType = nil
                                    if team.getPhoneNumbers().isEmpty == false {
                                        self.sentError = .uncalledTeams([team])
                                    } else {
                                        self.sentError = .messageNotSent
                                    }
                                }
                            @unknown default:
                                break
                            }
                        }
                    } else {
                        SubscriptionView(isPresented: self.$showSubscriptionView, showLackOfPlanMessage: true)
                            .environment(\.colorScheme, .light)
                    }
                case .mail(_, let recipients, let bccRecipients, let body, let subject, _):
                    if Guard.main.paymentForNewTournament() != nil {
                        MailComposeView(recipients: recipients, bccRecipients: bccRecipients, body: body, subject: subject) { result in
                            switch result {
                            case .cancelled, .saved:
                                self.contactType = nil
                            case .failed:
                                self.contactType = nil
                                self.sentError = .mailFailed
                            case .sent:
                                if networkMonitor.connected == false {
                                    self.contactType = nil
                                    if team.getMail().isEmpty == false {
                                        self.sentError = .uncalledTeams([team])
                                    } else {
                                        self.sentError = .mailNotSent
                                    }
                                }
                            @unknown default:
                                break
                            }
                        }
                    } else {
                        SubscriptionView(isPresented: self.$showSubscriptionView, showLackOfPlanMessage: true)
                            .environment(\.colorScheme, .light)
                    }
                }
            }
            .tint(.master)
        }
        .fullScreenCover(item: $editedTeam) { editedTeam in
            NavigationStack {
                AddTeamView(tournament: tournament, editedTeam: editedTeam)
            }
            .tint(.master)
        }
        .toolbar {
            ToolbarItem(placement: .topBarTrailing) {
                MenuWarningView(tournament: tournament, teams: [team], contactType: $contactType)
            }
        }
        .onChange(of: registrationDate) {
            if canSaveWithoutWarning() {
                team.registrationDate = registrationDate
                _save()
            }
        }
        .onChange(of: [walkOut, wildCardBracket, wildCardGroupStage]) {
            if canSaveWithoutWarning() {
                _resetTeam()
                team.walkOut = walkOut
                team.wildCardBracket = wildCardBracket
                team.wildCardGroupStage = wildCardGroupStage
                _save()
            }
        }
        .toolbarBackground(.visible, for: .navigationBar)
        .navigationTitle("Édition de l'équipe")
        .navigationBarTitleDisplayMode(.inline)
    }
    
    func canSaveWithoutWarning() -> Bool {
        (tournament.shouldWarnOnlineRegistrationUpdates() && tournament.teamCount <= tournament.unsortedTeamsCount()) == false
    }
    
    private var confirmationReceived: Binding<Bool> {
        Binding {
            team.confirmed()
        } set: { confirmed in
            team.confirmationDate = confirmed ? Date() : nil
            do {
                try tournamentStore?.teamRegistrations.addOrUpdate(instance: team)
            } catch {
                Logger.error(error)
            }
        }
    }

    private var hasArrived: Binding<Bool> {
        Binding {
            team.isHere()
        } set: { hasArrived in
            team.unsortedPlayers().forEach {
                $0.hasArrived = hasArrived
            }
            do {
                try tournamentStore?.playerRegistrations.addOrUpdate(contentOfs: team.unsortedPlayers())
            } catch {
                Logger.error(error)
            }
        }
    }
    
    private func _save() {
        do {
            try tournamentStore?.teamRegistrations.addOrUpdate(instance: team)
        } catch {
            Logger.error(error)
        }
    }
    
    private var _networkErrorMessage: String {
        ContactManagerError.getNetworkErrorMessage(sentError: sentError, networkMonitorConnected: networkMonitor.connected)
    }
}

//#Preview {
//    EditingTeamView(team: TeamRegistration.mock())
//}
