//
//  PrintSettingsView.swift
//  Padel Tournament
//
//  Created by Razmig Sarkissian on 23/10/2023.
//

import SwiftUI
import WebKit

struct PrintSettingsView: View {
    let tournament: Tournament
    @StateObject var generator: HtmlGenerator
    @State private var presentShareView: Bool = false
    @State private var prepareGroupStage: Bool = false
    @State private var generationId: UUID = UUID()
    @State private var generationGroupStageId: UUID = UUID()
    @State private var generating: Bool = false
    
    init(tournament: Tournament) {
        self.tournament = tournament
        _generator = StateObject(wrappedValue: HtmlGenerator(tournament: tournament))
    }
    
    var body: some View {
        List {
            Section {
//                Toggle(isOn: $generator.displayHeads, label: {
//                    Text("Afficher les têtes de séries")
//                })
                
                Toggle(isOn: $generator.displayRank, label: {
                    Text("Afficher le classement du joueur")
                })
                
                Toggle(isOn: $generator.includeBracket, label: {
                    Text("Tableau")
                })

//                Toggle(isOn: $generator.includeLoserBracket, label: {
//                    Text("Tableau des matchs de classements")
//                })
                
                if tournament.groupStages().isEmpty == false {
                    Toggle(isOn: $generator.includeGroupStage, label: {
                        Text("Poules")
                    })
                }
            }
            
            if generator.includeBracket {
                Section {
                    Picker(selection: $generator.zoomLevel) {
                        Text("1 page").tag(nil as Optional<CGFloat>)
                        Text("50%").tag(2.0 as Optional<CGFloat>)
                        Text("100%").tag(1.0 as Optional<CGFloat>)
                    } label: {
                        Text("Zoom")
                    }
                    
                    HStack {
                        Text("Nombre de page A4 à imprimer")
                        Spacer()
                        Text(generator.estimatedPageCount.formatted())
                    }
                } header: {
                    Text("Tableau principal")
                }
                
                if generating == false {
                    RowButtonView("Générer le PDF", systemImage: "printer") {
                        await MainActor.run() {
                            self.generating = true
                        }
                        generator.preparePDF { result in
                            switch result {
                            case .success(true):
                                if generator.includeGroupStage && generator.groupStageIsReady == false && tournament.groupStages().isEmpty == false {
                                    self.prepareGroupStage = true
                                    self.generationGroupStageId = UUID()
                                } else {
                                    self.presentShareView = true
                                    self.generating = false
                                }
                            case .success(false):
                                print("didn't save pdf")
                                break
                            case .failure(let error):
                                print(error)
                                break
                            }
                        }
                        self.prepareGroupStage = false
                        self.generationId = UUID()
                    }
                    .disabled(generator.includeBracket == false && generator.includeGroupStage == false && generator.includeLoserBracket == false)
                } else {
                    LabeledContent {
                        ProgressView()
                    } label: {
                        Text("Préparation du PDF")
                    }
                    .id(generationId)
                }
            }
            
            Section {
                NavigationLink {
                    WebViewPreview(bracket: true)
                        .environmentObject(generator)
                } label: {
                    Text("Aperçu du tableau")
                }
                ForEach(tournament.groupStages()) { groupStage in
                    NavigationLink {
                        WebViewPreview(groupStage: groupStage)
                            .environmentObject(generator)
                    } label: {
                        Text("Aperçu de la \(groupStage.groupStageTitle())")
                    }
                }
            }
        }
        .background {
            if generating {
                _backgroundGenerationWebView()
                _backgroundGroupStageWebView()
            }
        }
        .navigationTitle("Imprimer")
        .toolbarBackground(.visible, for: .navigationBar)
        .navigationBarTitleDisplayMode(.inline)
//        .toolbar {
//            ToolbarItem(placement: .topBarTrailing) {
//                Menu {
//                    Section {
//                        ShareLink(item: generator.generateHtml()) {
//                            Text("Tableau")
//                        }
//                        
//                        if let groupStage = tournament.groupStages().first {
//                            ShareLink(item: HtmlService.groupstage(groupStage: groupStage).html(headName: generator.displayHeads, withRank: generator.displayRank, withScore: false)) {
//                                Text("Poule")
//                            }
//                        }
//                    } header: {
//                        Text("Partager le code source HTML")
//                    }
//                } label: {
//                    Label("Options", systemImage: "ellipsis.circle")
//                }
//            }
//        }
        .sheet(isPresented: $presentShareView) {
            if let pdfURL = generator.pdfURL {
                ShareSheet(urls: [pdfURL])
            }
        }
    }
    
    @ViewBuilder
    private func _backgroundGenerationWebView() -> some View {
        WebView(htmlRawData: generator.generateHtml(), loadStatusChanged: { loaded, error, webView in
            if let error {
                print("preparePDF", error)
            } else if loaded == false {
                generator.generateWebView(webView: webView)
            } else {
                print("preparePDF", "is loading")
            }
        })
        .opacity(0)
        .id(generationId)
    }
    
    private func _backgroundGroupStageWebView() -> some View {
        Group {
            if prepareGroupStage {
                ForEach(tournament.groupStages()) { groupStage in
                    WebView(htmlRawData: HtmlService.groupstage(groupStage: groupStage).html(headName: generator.displayHeads, withRank: generator.displayRank, withScore: false), loadStatusChanged: { loaded, error, webView in
                        if let error {
                            print("preparePDF", error)
                        } else if loaded == false {
                            generator.generateGroupStage(webView: webView)
                        } else {
                            print("preparePDF", "is loading")
                        }
                    }).opacity(0)
                }
            }
        }
        .id(generationGroupStageId)
    }
}

// MARK: Share Sheet
struct ShareSheet: UIViewControllerRepresentable{
    
    var urls: [Any]
    
    func makeUIViewController(context: Context) -> UIActivityViewController {
        let controller = UIActivityViewController(activityItems: urls, applicationActivities: nil)
        
        return controller
    }
    
    func updateUIViewController(_ uiViewController: UIActivityViewController, context: Context) {
        
    }
}

struct WebView: UIViewRepresentable {
    var htmlRawData: String? = nil
    var url: URL? = nil
    var loadStatusChanged: ((Bool, Error?, WKWebView) -> Void)? = nil

    func makeCoordinator() -> WebView.Coordinator {
        Coordinator(self)
    }

    func makeUIView(context: Context) -> WKWebView {
        let view = WKWebView()
        view.navigationDelegate = context.coordinator
        
        if let htmlRawData {
            view.loadHTMLString(htmlRawData, baseURL: nil)
        }
        if let url {
            view.loadFileURL(url, allowingReadAccessTo: url)
        }
        return view
    }

    func updateUIView(_ uiView: WKWebView, context: Context) {
        // you can access environment via context.environment here
        // Note that this method will be called A LOT
    }

    class Coordinator: NSObject, WKNavigationDelegate {
        let parent: WebView

        init(_ parent: WebView) {
            self.parent = parent
        }

        func webView(_ webView: WKWebView, didCommit navigation: WKNavigation!) {
            parent.loadStatusChanged?(true, nil, webView)
        }

        func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
            parent.loadStatusChanged?(false, nil, webView)
        }

        func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) {
            parent.loadStatusChanged?(false, error, webView)
        }
    }
}


struct WebViewPreview: View {
    @EnvironmentObject var generator: HtmlGenerator
    let bracket: Bool
    let groupStage: GroupStage?
    
    @State private var html: String?
    
    init(bracket: Bool = false, groupStage: GroupStage? = nil) {
        self.bracket = bracket
        self.groupStage = groupStage
    }
    
    var body: some View {
        Group {
            if let html {
                WebView(htmlRawData: html, loadStatusChanged: { loaded, error, webView in
                })
            } else {
                ProgressView()
                    .onAppear {
                        if let groupStage {
                            html = HtmlService.groupstage(groupStage: groupStage).html(headName: generator.displayHeads, withRank: generator.displayRank, withScore: false)
                        } else {
                            html = generator.generateHtml()
                        }
                    }
            }
        }
    }
}
