//
//  AddHashtagPinnedTimelineView.swift
//  Tusker
//
//  Created by Shadowfacts on 12/20/22.
//  Copyright © 2022 Shadowfacts. All rights reserved.
//

import SwiftUI
import Pachyderm

@available(iOS, obsoleted: 16.0)
struct AddHashtagPinnedTimelineRepresentable: UIViewControllerRepresentable {
    typealias UIViewControllerType = UIHostingController<AddHashtagPinnedTimelineView>
    
    @Binding var pinnedTimelines: [PinnedTimeline]
    
    func makeUIViewController(context: Context) -> UIHostingController<AddHashtagPinnedTimelineView> {
        return UIHostingController(rootView: AddHashtagPinnedTimelineView(pinnedTimelines: $pinnedTimelines))
    }
    
    func updateUIViewController(_ uiViewController: UIHostingController<AddHashtagPinnedTimelineView>, context: Context) {
    }
}

struct AddHashtagPinnedTimelineView: View {
    @EnvironmentObject private var mastodonController: MastodonController
    @Environment(\.dismiss) private var dismiss
    
    @Binding var pinnedTimelines: [PinnedTimeline]
    @StateObject private var viewModel = SearchViewModel()
    @State private var searchTask: Task<Void, Never>?
    @State private var isSearching = false
    @State private var searchResults: [String] = []
    @State private var trendingTags: [String] = []
    
    private var savedAndFollowedHashtags: [String] {
        var tags = Set<String>()
        let req = SavedHashtag.fetchRequest(account: mastodonController.accountInfo!)
        for saved in (try? mastodonController.persistentContainer.viewContext.fetch(req)) ?? [] {
            tags.insert(saved.name)
        }
        for followed in mastodonController.followedHashtags {
            tags.insert(followed.name)
        }
        return tags.sorted(using: SemiCaseSensitiveComparator())
    }
    
    var body: some View {
        NavigationView {
            list
                .appGroupedListBackground(container: AddHashtagPinnedTimelineRepresentable.UIViewControllerType.self)
                .listStyle(.grouped)
                .navigationTitle("Add Hashtag")
                .navigationBarTitleDisplayMode(.inline)
                .searchable(text: $viewModel.searchQuery, placement: .navigationBarDrawer(displayMode: .always), prompt: Text("Search for hashtags"))
                .autocorrectionDisabled()
                .textInputAutocapitalization(.never)
                .toolbar {
                    ToolbarItem(placement: .cancellationAction) {
                        Button("Cancel") {
                            dismiss()
                        }
                    }
                }
        }
        .navigationViewStyle(.stack)
        .onReceive(viewModel.$searchQuery, perform: { newValue in
            isSearching = !newValue.isEmpty
        })
        .onReceive(viewModel.$searchQuery.debounce(for: .milliseconds(500), scheduler: DispatchQueue.main), perform: { _ in
            searchTask?.cancel()
            searchTask = Task {
                try? await updateSearchResults()
            }
        })
        .task {
            await fetchTrendingTags()
        }
    }
    
    private var list: some View {
        List {
            if !viewModel.searchQuery.isEmpty {
                Section {
                    ProgressView()
                        .progressViewStyle(.circular)
                        .opacity(isSearching ? 1 : 0)
                        .animation(.linear(duration: 0.1), value: isSearching)
                        .frame(maxWidth: .infinity, alignment: .center)
                        .listRowBackground(EmptyView())
                        .listRowSeparator(.hidden)
                    
                    forEachTag(searchResults)
                }
                .appGroupedListRowBackground()
            }
            
            if !savedAndFollowedHashtags.isEmpty {
                Section {
                    forEachTag(savedAndFollowedHashtags)
                } header: {
                    Text("Saved and Followed Hashtags")
                }
                .appGroupedListRowBackground()
            }
            
            if !trendingTags.isEmpty {
                Section {
                    forEachTag(trendingTags)
                } header: {
                    Text("Trending Hashtags")
                }
                .appGroupedListRowBackground()
            }
        }
    }
    
    private func forEachTag(_ tags: [String]) -> some View {
        ForEach(tags, id: \.self) { tag in
            Button {
                pinnedTimelines.append(.tag(hashtag: tag))
                dismiss()
            } label: {
                Text("#\(tag)")
            }
            .tint(.primary)
            .disabled(pinnedTimelines.contains(.tag(hashtag: tag)))
        }
    }
    
    private func updateSearchResults() async throws {
        guard !viewModel.searchQuery.isEmpty else {
            return
        }
        isSearching = true
        let req = Client.search(query: viewModel.searchQuery, types: [.hashtags])
        let (results, _) = try await mastodonController.run(req)
        searchResults = results.hashtags.map(\.name)
        isSearching = false
    }
    
    private func fetchTrendingTags() async {
        guard mastodonController.instanceFeatures.trends else { return }
        let req = Client.getTrendingHashtags()
        if let (results, _) = try? await mastodonController.run(req) {
            trendingTags = results.map(\.name)
        }
    }
}

private class SearchViewModel: ObservableObject {
    @Published var searchQuery = ""
}

//struct AddHashtagPinnedTimelineView_Previews: PreviewProvider {
//    static var previews: some View {
//        AddHashtagPinnedTimelineView()
//    }
//}
