//
//  TournamentSubscriptionView.swift
//  PadelClub
//
//  Created by Razmig Sarkissian on 09/09/2024.
//

import SwiftUI
import EventKit

struct TournamentSubscriptionView: View {
    @EnvironmentObject var networkMonitor: NetworkMonitor

    let federalTournament: FederalTournament
    let build: any TournamentBuildHolder
    let user: CustomUser
    
    @State private var selectedPlayers: [ImportedPlayer]
    @State private var contactType: ContactType? = nil
    @State private var sentError: ContactManagerError? = nil
    @State private var didSendMessage: Bool = false
    @State private var didSaveInCalendar: Bool = false

    init(federalTournament: FederalTournament, build: any TournamentBuildHolder, user: CustomUser) {
        self.federalTournament = federalTournament
        self.build = build
        self.user = user
        _selectedPlayers = .init(wrappedValue: [user.currentPlayerData()].compactMap({ $0 }))
    }
    
    func hasPartner() -> Bool {
        selectedPlayers.count == 2
    }
    
    func inscriptionSent() -> Bool {
        didSendMessage
    }
    
    func addEvent() {
        let eventStore = EKEventStore()

        eventStore.requestWriteOnlyAccessToEvents { (granted, error) in
            if granted && error == nil {
                print("Access granted")
                let startDate = federalTournament.startDate
                let endDate = federalTournament.dateFin ?? federalTournament.startDate.endOfDay()
                addEventToCalendar(title: messageSubject, startDate: startDate, endDate: endDate)
                didSaveInCalendar = true
            } else {
                print("Access denied or error occurred: \(String(describing: error?.localizedDescription))")
                sentError = .calendarAccessDenied
            }
        }

    }
    
    func addEventToCalendar(title: String, startDate: Date, endDate: Date) {
        let eventStore = EKEventStore()
        if eventStore.defaultCalendarForNewEvents == nil {
            sentError = .noCalendarAvailable
            return
        }
        eventStore.requestWriteOnlyAccessToEvents { (granted, error) in
            if granted && error == nil {
                let event = EKEvent(eventStore: eventStore)
                event.title = title
                event.isAllDay = true
                event.startDate = startDate
                event.endDate = endDate
                event.calendar = eventStore.defaultCalendarForNewEvents
                event.notes = noteCalendar
                event.location = federalTournament.clubLabel()
                do {
                    try eventStore.save(event, span: .thisEvent)
                    didSaveInCalendar = true
                    print("Event saved")
                } catch let error {
                    print("Failed to save event: \(error.localizedDescription)")
                    sentError = .calendarEventSaveFailed
                }
            } else {
                print("Access denied or error occurred: \(String(describing: error?.localizedDescription))")
                sentError = .calendarAccessDenied
            }
        }
    }

    
    var body: some View {
        List {
            Section {
                LabeledContent("Tournoi") {
                    Text(federalTournament.libelle ?? "Tournoi")
                }
                LabeledContent("Club") {
                    Text(federalTournament.clubLabel())
                }
                LabeledContent("Épreuve") {
                    Text(build.buildHolderTitle(.wide))
                }
                
                LabeledContent("JAP") {
                    Text(federalTournament.umpireLabel())
                }
                LabeledContent("Mail") {
                    Text(federalTournament.mailLabel())
                }
                LabeledContent("Téléphone") {
                    Text(federalTournament.phoneLabel())
                }
            } header: {
                Text("Informations")
            }
            
            Section {
                ForEach(selectedPlayers) { teamPlayer in
                    NavigationLink {
                        SelectablePlayerListView(allowSelection: 1, playerSelectionAction: { players in
                            if let player = players.first {
                                selectedPlayers.remove(elements: [teamPlayer])
                                selectedPlayers.append(player)
                            }
                        })
                    } label: {
                        ImportedPlayerView(player: teamPlayer)
                    }
                }
                
                if selectedPlayers.count < 2 {
                    NavigationLink {
                        SelectablePlayerListView(allowSelection: 1, playerSelectionAction: { players in
                            if let player = players.first {
                                selectedPlayers.append(player)
                            }
                        })
                    } label: {
                        Text("Choisir un partenaire")
                    }
                }
            } header: {
                if selectedPlayers.isEmpty == false {
                    HStack {
                        Text("Poids de l'équipe")
                        Spacer()
                        Text(selectedPlayers.map { $0.rank }.reduce(0, +).formatted())
                    }
                }
            }
            
            Section {
                Text(messageBody)
            } header: {
                Text("Message preparé par Padel Club")
            } footer: {
                CopyPasteButtonView(pasteValue: messageBody)
            }
        }
        .toolbarBackground(.visible, for: .bottomBar)
        .toolbarBackground(.visible, for: .navigationBar)
        .overlay(alignment: .bottom) {
            if didSaveInCalendar {
                Label("Ajouté dans votre calendrier par défaut", systemImage: "checkmark")
                    .toastFormatted()
                    .deferredRendering(for: .seconds(3))
            }
        }
        .toolbar(content: {
            ToolbarItem(placement: .status) {
                Menu {
                    if let courrielEngagement = federalTournament.courrielEngagement {
                        Section {
                            RowButtonView("S'inscrire par email", systemImage: "envelope") {
                                contactType = .mail(date: nil, recipients: [courrielEngagement], bccRecipients: nil, body: messageBody, subject: messageSubject, tournamentBuild: build as? TournamentBuild)
                            }
                        }
                    }
                    
                    if let installation = federalTournament.installation, let telephone = installation.telephone {
                        if telephone.isMobileNumber() {
                            Section {
                                RowButtonView("S'inscrire par message", systemImage: "message") {
                                    contactType = .message(date: nil, recipients: [telephone], body: messageBodyShort, tournamentBuild: build as? TournamentBuild)
                                }
                            }
                        }
                        let number = telephone.replacingOccurrences(of: " ", with: "")
                        if let url = URL(string: "tel:\(number)") {
                            Link(destination: url) {
                                Label("Appeler", systemImage: "phone")
                            }
                        }
                    }
                } label: {
                    Text("Contact et inscription")
                }
                .menuStyle(.button)
                .buttonStyle(.borderedProminent)
                .offset(y:-2)
            }
            
            ToolbarItem(placement: .topBarTrailing) {
                Menu {
                    ShareLink(item: federalTournament.sharePartnerMessage) {
                        Label("Prévenir votre partenaire", systemImage: "person.2")
                    }
                    
                    Button("Ajouter à votre agenda", systemImage: "calendar") {
                        addEvent()
                    }
                    
                    Link(destination: URL(string:"https://tenup.fft.fr/tournoi/\(federalTournament.id)")!) {
                        Label("Voir sur Tenup", systemImage: "tennisball")
                    }
                    ShareLink(item: federalTournament.shareMessage) {
                        Label("Partager les infos", systemImage: "info")
                    }
                } label: {
                    LabelOptions()
                }
            }
        })
        .alert("Un problème est survenu", isPresented: messageSentFailed) {
            Button("OK") {
            }
            
            if case .calendarAccessDenied = sentError {
                Button("Voir vos réglages") {
                    openAppSettings()
                }
            }
            if case .noCalendarAvailable = sentError{
                Button("Voir vos réglages") {
                    openAppSettings()
                }
            }

        } message: {
            Text(_networkErrorMessage)
        }
        .sheet(item: $contactType) { contactType in
            Group {
                switch contactType {
                case .message(_, let recipients, let body, _):
                    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
                            } else {
                                self.didSendMessage = true
                            }
                        @unknown default:
                            break
                        }
                    }
                case .mail(_, let recipients, let bccRecipients, let body, let subject, _):
                    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
                            } else {
                                self.didSendMessage = true
                            }
                        @unknown default:
                            break
                        }
                    }
                }
            }
            .tint(.master)
        }
        .navigationBarTitleDisplayMode(.inline)
        .toolbarBackground(.visible, for: .navigationBar)
        .navigationTitle("Détail du tournoi")
    }
    
    var teamsString: String {
        selectedPlayers.map { $0.pasteData(withRank: true) }.joined(separator: "\n")
    }
    
    var messageBody: String {
        let bonjourOuBonsoir = Date().timeOfDay.hello
        let bonneSoireeOuBonneJournee = Date().timeOfDay.goodbye
        let body = [["\(bonjourOuBonsoir),\n\nJe souhaiterais inscrire mon équipe au tournoi : ", build.buildHolderTitle(.wide), "du", federalTournament.computedStartDate, "au", federalTournament.clubLabel() + ".\n"].compacted().joined(separator: " "), teamsString, "\nCordialement,\n", user.fullName() ?? bonneSoireeOuBonneJournee, "----------------------------------\nCe message a été préparé grâce à l'application Padel Club !\n\(URLs.appStore.rawValue)"].compactMap { $0 }.joined(separator: "\n") + "\n"
        return body
    }
    
    var messageBodyShort: String {
        let bonjourOuBonsoir = Date().timeOfDay.hello
        let bonneSoireeOuBonneJournee = Date().timeOfDay.goodbye
        let body = [["\(bonjourOuBonsoir),\n\nJe souhaiterais inscrire mon équipe au tournoi : ", build.buildHolderTitle(.wide), "du", federalTournament.computedStartDate, "au", federalTournament.clubLabel() + ".\n"].compacted().joined(separator: " "), teamsString, "\nCordialement,\n", user.fullName() ?? bonneSoireeOuBonneJournee, "----------------------------------\nCe message a été préparé grâce à l'application Padel Club !\n\(URLs.appStore.rawValue)"].compactMap { $0 }.joined(separator: "\n") + "\n"
        return body
    }
    
    var noteCalendar: String {
        let body = [[build.buildHolderTitle(.wide), "du", federalTournament.computedStartDate, "au", federalTournament.clubLabel() + ".\n"].compacted().joined(separator: " "), teamsString, federalTournament.calendarNoteMessage()].compactMap { $0 }.joined(separator: "\n") + "\n"
        return body
    }
    
    var messageSubject: String {
        let subject = [build.buildHolderTitle(.wide), federalTournament.clubLabel()].compacted().joined(separator: " ")
        return subject
    }
    
    var messageSentFailed: Binding<Bool> {
        Binding {
            sentError != nil
        } set: { newValue in
            if newValue == false {
                sentError = nil
            }
        }
    }
    
    private var _networkErrorMessage: String {
        ContactManagerError.getNetworkErrorMessage(sentError: sentError, networkMonitorConnected: networkMonitor.connected)
    }
    
    func openAppSettings() {
        if let appSettings = URL(string: UIApplication.openSettingsURLString) {
            if UIApplication.shared.canOpenURL(appSettings) {
                UIApplication.shared.open(appSettings, options: [:], completionHandler: nil)
            }
        }
    }

}
