import UIKit
import SwiftUI

private struct OffsetPreferenceKey: PreferenceKey {
    static var defaultValue: CGPoint = .zero
    static func reduce(value: inout CGPoint, nextValue: () -> CGPoint) { }
}

struct PostDetailView: View {
    private enum CommentSortOrder: String, CaseIterable {
        case newest
        case oldest
        case popular
        
        var title: String {
            switch self {
            case .newest:
                return "Newest"
                
            case .oldest:
                return "Oldest"
                
            case .popular:
                return "Most Popular"
            }
        }
    }
    
    private enum CommentSource: String, CaseIterable {
        case all
        case wordpress
        case facebook
        
        var title: String {
            switch self {
            case .all:
                return "All Comments"
                
            case .wordpress:
                return "Riotact Only"
                
            case .facebook:
                return "Facebook Only"
            }
        }
    }
    
    enum ViewState: String, CaseIterable {
        case article
        case conversation
        
        var title: String {
            rawValue.capitalized
        }
    }
    
    @EnvironmentObject var contentService: ContentService
    @EnvironmentObject var userService: UserService
    @EnvironmentObject var analyticsService: AnalyticsService
    
    @State var post: Post
    @State var viewState: ViewState = .article
    
    @State private var bodyHeight: CGFloat = 0
    @State private var loadedComments: Bool = false
    @State private var comments: [Comment] = []
    @State private var banner: Banner?
    private let adSlot: GADSlot = .articleDetail
    
    var filteredComments: [Comment] {
        let ordered = comments.sorted { lhs, rhs in
            switch commentSort {
                
            case .newest:
                return lhs.date > rhs.date
            case .oldest:
                return lhs.date < rhs.date
            case .popular:
                return lhs.children.count > rhs.children.count
            }
        }
        
        return ordered.filter { comment in
            switch commentSource {
            case .all:
                return true
            case .wordpress:
                return comment.source == .wordpress
            case .facebook:
                return comment.source == .facebook
            }
        }
    }
    
    @State private var contentDeeplink: Deeplink? = nil
    @State private var showExtraCommentButton: Bool = false
    
    var body: some View {
        ScrollViewWithBanner(banner: banner, onRefresh: refreshPost) { scrollProxy in
            VStack(alignment: .center, spacing: 6) {
                let contentDeeplinkSelectionBinding = Binding<Bool> {
                    return contentDeeplink != nil

                } set: { newValue in
                    if newValue == false {
                        contentDeeplink = nil
                    }
                }
                NavigationLink(destination: DeeplinkWrapper(deeplink: contentDeeplink), isActive: contentDeeplinkSelectionBinding) { EmptyView() }
                
                PostHeaderView(summary: post.summary, onCommentStatusTap: {
                    viewState = .conversation
                })
                .padding(.horizontal)
                .padding(.top, 26)
                .padding(.bottom, 18)
                .onChange(of: viewState) { _ in
                    withAnimation {
                        scrollProxy.scrollTo("banner", anchor: .bottom)
                    }
                }
                
                GeometryReader { proxy in
                    Color.clear
                        .preference(
                            key: OffsetPreferenceKey.self,
                            value: proxy.frame(
                                in: .named("ScrollViewOrigin")
                            ).origin
                        )
                }
                .frame(height: 0)
                .onPreferenceChange(OffsetPreferenceKey.self, perform: { value in
                    showExtraCommentButton = value.y < -(24 + 50)
                })
                
                if viewState == .article {
                    HTMLView(dynamicHeight: $bodyHeight, html: post.content.rendered, assets: contentService.ignoreExternalWebAssets ? [] : post.webAssets, ignoreAppCSS: contentService.ignoreAppCSS, handleDeeplinks: { deeplink in
                        contentDeeplink = deeplink
                    })
                        .frame(height: bodyHeight)
                        .opacity(bodyHeight == 0 ? 0 : 1)
                        .padding(.horizontal, 10)
                    
                    AdView(adSlot: adSlot)
                    
                    if post.commentStatus == .open {
                        ConversationButton(postId: post.id, hasComments: post.commentCount > 0)
                            .padding()
                    }
                    
                    if !post.relatedPosts.isEmpty {
                        Divider()
                            .padding(.top, 30)
                        
                        HStack {
                            Text("Related Articles")
                                .textStyle(.title3)
                                .multilineTextAlignment(.leading)
                            
                            Spacer()
                        }
                        .padding()
                        
                        PostListingView(posts: post.relatedPosts, showYear: true, articlesPerAd: 0)
                    }
                    
                } else {
                    if post.commentStatus == .open {
                        PostConversations(post: post, showHeader: false, commentSource: loadedComments ? .provided(filteredComments) : .loading )
                        .padding()
                        .padding(.bottom, 60)
                    } else {
                        VStack {
                            Spacer()
                            Text("Conversations are closed for this article.")
                                .textStyle(.headline, color: ColorName.text.color(variation: .tertiary))
                            Spacer()
                        }
                    }
                }
            }
            .background(ColorName.background.color)
        }
        .overlay(
            BookmarksTipView()
        )

        .toolbar {
            ToolbarItem(placement: .principal) {
                let selection = Binding<Int> {
                    return ViewState.allCases.firstIndex(of: viewState) ?? 0
                } set: { newValue in
                    viewState = ViewState.allCases[newValue]
                }
                
                SegmentedControlView(selection: selection,
                                     itemCount: ViewState.allCases.count) { index in
                    switch ViewState.allCases[index] {
                    case .article:
                        HStack(alignment: .center, spacing: 0) {
                            Spacer()
                            Text(ViewState.allCases[index].title)
                                .textStyle(.segmentedControl, color: ColorName.text.color)
                            Spacer()
                        }
                        
                    case .conversation:
                        HStack(alignment: .center, spacing: 0) {
                            Spacer()
                            Text(ViewState.allCases[index].title)
                                .textStyle(.segmentedControl, color: ColorName.text.color)
                                .overlay(conversationCountView)
                            
                            Spacer()
                        }
                    }
                }
                                     .frame(width: UIDevice.current.userInterfaceIdiom == .pad ? 400 : 285 )
            }
            ToolbarItem(placement: .navigationBarTrailing) {
                ZStack {
                    Button(action: {
                        if let url = post.link {
                            shareSheet(url: url)
                        }
                    }, label: {
                        ImageName.System.share.image
                    })
                    .disabled(viewState != .article)
                    .opacity(viewState == .article ? 1 : 0)
                    
                    conversationContextMenu()
                        .disabled(viewState != .conversation)
                        .opacity(viewState == .conversation ? 1 : 0)
                    
                }
                .animation(.easeInOut, value: viewState)
            }
            
        }
        .onAppear {
            refreshPost()
            analyticsService.articleWasViewed(postId: post.id)
        }
        .overlay(
            VStack {
                Spacer()
                if post.commentStatus == .open, viewState == .conversation {
                    
                    ConversationButton(postId: post.id, hasComments: post.commentCount > 0)
                        .padding()
                        .background(
                            LinearGradient(colors: [ColorName.background.color.opacity(0),ColorName.background.color], startPoint: .top, endPoint: .bottom)
                        )
                        .offset(y: showExtraCommentButton ? 0 : 400)
                        .animation(.easeInOut, value: showExtraCommentButton)
                }
            }
        )
    }
    
    private func refreshPost() {
        Task {
            do {
                let post = try await contentService.hydratePost(post.id, force: true)
                if post.isHydrated {
                    self.comments = post.allComments ?? []
                } else {
                    // Throw?
                }
                
                if self.banner == nil {
                    let banner = contentService.bannerForPosition(.post(postId: post.id))
                    withAnimation {
                        self.banner = banner
                    }
                }
                self.post = post
                self.loadedComments = true
            } catch {
                self.comments = []
                self.banner = nil
                self.loadedComments = true
            }
        }
    }
    
    func shareSheet(url: URL) {
        let activityView = UIActivityViewController(activityItems: [url], applicationActivities: nil)

        let allScenes = UIApplication.shared.connectedScenes
        let scene = allScenes.first { $0.activationState == .foregroundActive }

        if let windowScene = scene as? UIWindowScene {
            let window: UIWindow?
            if #available(iOS 15.0, *) {
                window = windowScene.keyWindow
            } else {
                window = windowScene.windows.first
            }
            
            if let window = window {
                window.rootViewController?.present(activityView, animated: true, completion: nil)
            }
        }

    }
    
    @State private var commentSort: CommentSortOrder = .newest
    @State private var commentSource: CommentSource = .all
    
    @ViewBuilder func conversationContextMenu() -> some View {
        Menu {
            Section(header: Text("Sorting")) {
                Picker(selection: $commentSort, label: Text("Sorting options")) {
                    ForEach(CommentSortOrder.allCases, id: \.self) { sortOption in
                        Text(sortOption.title).tag(sortOption)
                    }
                }
            }
                
            Section(header: Text("Show")) {
                Picker(selection: $commentSource, label: Text("Source")) {
                    ForEach(CommentSource.allCases, id: \.self) { source in
                        Text(source.title).tag(source)
                    }
                }
            }
            
            
        } label: {
            ImageName.System.sort.image
        }
    }
    
    @ViewBuilder var conversationCountView: some View {
        if post.commentCount > 0 {
            HStack {
                Spacer()
                Text("\(post.commentCount)")
                    .textStyle(.count, color: ColorName.textOnTint.color)
                    .padding(.horizontal, 4)
                    .padding(.vertical, 1)
                    .frame(minWidth: 18)
                    .background(Capsule().fill(ColorName.tint.color))
                    .padding(.leading, 3)
                    .shadow(color: ColorName.shadow.color, radius: 3, x: 0, y: 1)
            }
            .offset(x: 20, y: -8)
        } else {
            EmptyView()
        }
    }
}


