//
//  MatchDetailView.swift
//  PadelClub
//
//  Created by Razmig Sarkissian on 23/03/2024.
//

import SwiftUI
import LeStorage

struct MatchDetailView: View {
    @EnvironmentObject var dataStore: DataStore
    @EnvironmentObject var networkMonitor: NetworkMonitor
    @Environment(\.dismiss) var dismiss
    let matchViewStyle: MatchViewStyle
    
    @State private var showLiveScore: Bool = false
    @State private var editScore: Bool = false
    @State private var scoreType: ScoreType?
    @State private var shareStat: Bool = false
    @State private var startDateSetup: MatchDateSetup = .now
    @State private var fieldSetup: MatchFieldSetup = .random
    @State private var broadcasted: Bool = false
    @State private var startDate: Date = Date()
    @State private var endDate: Date = Date()
    @State private var isEditing: Bool = false
    @State private var showDetails: Bool = false
    @State private var contactType: ContactType? = nil
    @State private var sentError: ContactManagerError? = nil
    @State private var showSubscriptionView: Bool = false
    
    var messageSentFailed: Binding<Bool> {
        Binding {
            sentError != nil
        } set: { newValue in
            if newValue == false {
                sentError = nil
            }
        }
    }

    var match: Match
    
    init(match: Match, matchViewStyle: MatchViewStyle = .standardStyle) {
        self.match = match
        self.matchViewStyle = matchViewStyle
        
        if match.hasStarted() == false && (match.startDate == nil || match.courtIndex == nil) {
            _isEditing = State(wrappedValue: true)
        }
        
        if let startDate = match.startDate {
            _startDateSetup = State(wrappedValue: .customDate)
            _startDate = State(wrappedValue: startDate)
        } else if match.isReady() == false {
            _startDateSetup = State(wrappedValue: .customDate)
        }
        
        if let endDate = match.endDate {
            _endDate = State(wrappedValue: endDate)
        }
        
        if let courtIndex = match.courtIndex {
            _fieldSetup = State(wrappedValue: .field(courtIndex))
        }
    }

    var quickLookHeader: some View {
        Section {
            HStack {
                Menu {
                    Button("Non défini") {
                        match.removeCourt()
                        save()
                    }
                    if let tournament = match.currentTournament() {
                        ForEach(0..<tournament.courtCount, id: \.self) { courtIndex in
                            Button(tournament.courtName(atIndex: courtIndex)) {
                                match.setCourt(courtIndex)
                                save()
                            }
                        }
                    }
                } label: {
                    VStack(alignment: .leading) {
                        Text("terrain").font(.footnote).foregroundStyle(.secondary)
                        if let courtName = match.courtName() {
                            Text(courtName)
                                .foregroundStyle(Color.master)
                                .underline()
                        } else {
                            Text("Choisir")
                                .foregroundStyle(Color.master)
                                .underline()
                        }
                    }
                }
                Spacer()
                MatchDateView(match: match, showPrefix: true)
            }
            .font(.title)
            .buttonStyle(.plain)
        } footer: {
//            if match.hasWalkoutTeam() == false {
//                if let weatherData = match.weatherData {
//                    HStack {
//                        WeatherView(weatherData: weatherData)
//                    }
//                }
//            }
        }
    }
    
    var body: some View {
        List {
            if match.hasWalkoutTeam() == false {
                if match.hasStarted() {
                    quickLookHeader
                } else {
                    startingOptionView
                }
            }
            
            Section {
                MatchSummaryView(match: match, matchViewStyle: .plainStyle)
            } footer: {
                if match.isEmpty() == false {
                    HStack {
                        FooterButtonView("Détails des joueurs") {
                            showDetails = true
                        }
                        Spacer()
                        MenuWarningView(teams: match.teams(), message: match.matchWarningMessage(), umpireMail: dataStore.user.email, subject: match.matchWarningSubject(), contactType: $contactType)
                            .buttonStyle(.borderless)
                    }
                }
            }
            
            if match.isReady() {
                Section {
                    RowButtonView("Saisir les résultats", systemImage: "list.clipboard") {
                        do {
                            if let tournament = self.match.currentTournament() {
                                try tournament.payIfNecessary()
                                scoreType = .edition
                            } else {
                                self.showSubscriptionView = true
                            }
                        } catch {
                            self.showSubscriptionView = true
                        }
                    }
                }
            }

            let players = match.teams().flatMap { $0.players() }
            let unpaid = players.filter({ $0.hasPaid() == false })

            if unpaid.isEmpty == false {
                Section {
                    DisclosureGroup {
                        ForEach(unpaid) { player in
                            LabeledContent {
                                PlayerPayView(player: player)
                            } label: {
                                Text(player.playerLabel())
                            }
                        }
                    } label: {
                        LabeledContent {
                            Text(unpaid.count.formatted() + " / " + players.count.formatted())
                        } label: {
                            Text("Encaissement manquant")
                        }
                    }
                }
            }
            
            menuView
        }
        .sheet(isPresented: $showDetails) {
            MatchTeamDetailView(match: match).tint(.master)
        }
        .sheet(isPresented: self.$showSubscriptionView, content: {
            NavigationStack {
                SubscriptionView(isPresented: self.$showSubscriptionView, showLackOfPlanMessage: true)
            }
        })
        .sheet(item: $scoreType, onDismiss: {
            if match.hasEnded() {
                dismiss()
            }
        }) { scoreType in
            let matchDescriptor = MatchDescriptor(match: match)
            EditScoreView(matchDescriptor: matchDescriptor)
                .tint(.master)

//            switch scoreType {
//            case .edition:
//                let matchDescriptor = MatchDescriptor(match: match)
//                EditScoreView(matchDescriptor: matchDescriptor)
//            case .live:
//                if let score = match.score {
//                    if score.sets.isEmpty {
//                        SplashView(score: score)
//                    } else {
//                        NewLiveScoringView(score: score)
//                    }
//                }
//            case .prepare:
//                if match.freeMatchTeams.isEmpty == false {
//                    EditFreeMatchView(match: match)
//                } else {
//                    PrepareMatchView(match: match)
//                }
//            case .stat:
//                if let score = match.score {
//                    MatchStatView()
//                        .environmentObject(score)
//                }
//            case .health:
//                HealthKitView(match: match)
//                    .presentationDetents([.medium])
//            case .feeling:
//                if let feedbackData = match.feedbackData {
//                    FeedbackView(feedbackData: feedbackData)
//                }
//            }
            
        }
        .alert("Un problème est survenu", isPresented: messageSentFailed) {
            Button("OK") {
            }
        } message: {
            let message = [networkMonitor.connected == false ? "L'appareil n'est pas connecté à internet." as String? : nil, sentError == .mailNotSent ? "Le mail est dans la boîte d'envoi de l'app Mail. Vérifiez son état dans l'app Mail avant d'essayer de le renvoyer." as String? : nil, (sentError == .messageFailed || sentError == .messageNotSent) ? "Le SMS n'a pas été envoyé" as String? : nil, sentError == .mailFailed ? "Le mail n'a pas été envoyé" as String? : nil].compacted().joined(separator: "\n")
            Text(message)
        }
        .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.sentError = .messageNotSent
                                }
                            @unknown default:
                                break
                            }
                        }
                    } else {
                        NavigationStack {
                            SubscriptionView(isPresented: self.$showSubscriptionView, showLackOfPlanMessage: true)
                        }
                    }
                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
                                    self.sentError = .mailNotSent
                                }
                            @unknown default:
                                break
                            }
                        }
                    } else {
                        NavigationStack {
                            SubscriptionView(isPresented: self.$showSubscriptionView, showLackOfPlanMessage: true)
                        }
                    }
                }
            }
            .tint(.master)
        }
        .toolbar {
            ToolbarItem(placement: .topBarTrailing) {
                Menu {
                    if match.courtIndex != nil {
                        Button(role: .destructive) {
                            match.removeCourt()
                            save()
                        } label: {
                            Text("Supprimer le terrain")
                        }
                    }
                    Button(role: .destructive) {
                        match.startDate = nil
                        match.endDate = nil
                        match.confirmed = false
                        save()
                    } label: {
                        Text("Supprimer l'horaire")
                    }

                    Button(role: .destructive) {
                        match.resetScores()
                        match.resetMatch()
                        match.confirmed = false
                        save()
                    } label: {
                        Text("Supprimer les scores")
                    }

                } label: {
                    LabelOptions()
                }
            }
        }
        .navigationTitle(match.matchTitle())
        .navigationBarTitleDisplayMode(.inline)
        .toolbarBackground(.visible, for: .navigationBar)
        
    }

    enum ScoreType: Int, Identifiable, Hashable {
        var id: Int {
            self.rawValue
        }
        case edition = 0
        case live = 1
        case prepare = 2
        case stat = 3
        case feeling = 4
        case health = 5
    }
    
    @ViewBuilder
    var menuView: some View {
        if match.hasStarted() {
            Section {
                editionView
            }
        }
        
        //todo
        //shareView

//        if let followUpMatch = match.followUpMatch {
//            Section {
//                MatchRowView(match: followUpMatch)
//            } header: {
//                Text("à suivre terrain \(match.fieldIndex)")
//            }
//        }
    }
    
    var editionView: some View {
        DisclosureGroup(isExpanded: $isEditing) {
            startingOptionView
        } label: {
            Text("Modifier l'horaire et le terrain")
        }
    }
    
    @ViewBuilder
    var startingOptionView: some View {
        if match.hasEnded() == false {
            let rotationDuration = match.getDuration()
            Picker(selection: $startDateSetup) {
                if match.isReady() {
                    Text("Dans 5 minutes").tag(MatchDateSetup.inMinutes(5))
                    Text("Dans 15 minutes").tag(MatchDateSetup.inMinutes(15))
                    Text("Tout de suite").tag(MatchDateSetup.now)
                }
                Text("Précédente rotation").tag(MatchDateSetup.inMinutes(-rotationDuration))
                Text("Prochaine rotation").tag(MatchDateSetup.inMinutes(rotationDuration))
                Text("À").tag(MatchDateSetup.customDate)
            } label: {
                Text("Horaire")
            }
            .onChange(of: startDateSetup) {
                switch startDateSetup {
                case .customDate:
                    break
                case .now:
                    startDate = Date()
                case .inMinutes(let minutes):
                    startDate = Date().addingTimeInterval(Double(minutes) * 60)
                }
            }
        }
        
        if match.startDate != nil || startDateSetup == .customDate {
            DatePicker(selection: $startDate) {
                Label("Début", systemImage: "calendar").labelStyle(.titleOnly)
            }
            .datePickerStyle(.compact)
        }
        
        if match.endDate != nil {
            DatePicker(selection: $endDate) {
                Label("Fin", systemImage: "calendar").labelStyle(.titleOnly)
            }
            .datePickerStyle(.compact)
        }


        Picker(selection: $fieldSetup) {
            Text("Au hasard").tag(MatchFieldSetup.random)
            //Text("Premier disponible").tag(MatchFieldSetup.firstAvailable)
            if let club = match.currentTournament()?.club() {
                ForEach(0..<club.courtCount, id: \.self) { courtIndex in
                    Text(club.courtName(atIndex: courtIndex))                            .tag(MatchFieldSetup.field(courtIndex))
                }
            } else if let tournament = match.currentTournament() {
                ForEach(0..<tournament.courtCount, id: \.self) { courtIndex in
                    Text(tournament.courtName(atIndex: courtIndex))                            .tag(MatchFieldSetup.field(courtIndex))
                }
            } else {
                ForEach(0..<20, id: \.self) { courtIndex in
                    Text(Court.courtIndexedTitle(atIndex: courtIndex))                            .tag(MatchFieldSetup.field(courtIndex))
                }
            }
        } label: {
            Text("Choix du terrain")
        }
        
        RowButtonView("Valider") {
            match.validateMatch(fromStartDate: startDateSetup == .now ? Date() : startDate, toEndDate: endDate, fieldSetup: fieldSetup)

            save()
            
            isEditing.toggle()
            
            if match.hasStarted() == false {
                dismiss()
            }
        }
    }
    
    private func save() {
        do {
            try dataStore.matches.addOrUpdate(instance: match)
        } catch {
            Logger.error(error)
        }
    }
}

//#Preview {
//    MatchDetailView(match: Match.mock(), matchViewStyle: .standardStyle)
//}
