import SwiftUI
import MapKit
import CoreLocation
import EventKit

struct EventPostDetailView: View {
    enum ViewState: String, CaseIterable {
        case overview
        case details
        
        var title: String {
            rawValue.capitalized
        }
    }
    
    @EnvironmentObject var contentService: ContentService
    @EnvironmentObject var analyticsService: AnalyticsService
    
    @State var post: Post
    @State var viewState: ViewState = .overview
    
    @State private var bodyHeight: CGFloat = 0
    @State private var banner: Banner?
    
    private let adSlot: GADSlot = .events
    
    var events: [Post.Event] {
        let today = Date()
        return post.events.sorted(by: { $0.startDate < $1.startDate }).filter { $0.startDate >= today }
    }

    var body: some View {
        ScrollViewWithBanner(banner: banner, onRefresh: refreshPost) { scrollProxy in
            VStack(alignment: .center, spacing: 6) {
                EventPostHeaderView(summary: post.summary)
                    .padding(.horizontal)
                    .padding(.top, 26)
                    .padding(.bottom, 18)
                    .onChange(of: viewState) { _ in
                        withAnimation {
                            scrollProxy.scrollTo("banner", anchor: .bottom)
                        }
                    }
                
                if viewState == .overview {
                    HTMLView(dynamicHeight: $bodyHeight, html: post.content.rendered, assets: contentService.ignoreExternalWebAssets ? [] : post.webAssets)
                        .frame(height: bodyHeight)
                        .opacity(bodyHeight == 0 ? 0 : 1)
                        .padding(.horizontal, 10)
                    
                    AdView(adSlot: adSlot)
                    
                } else {
                    VStack(alignment: .leading, spacing: 9) {
                        ForEach(events, id: \.self) { event in
                            EventSummaryView(post: post, event: event, isLast: event == post.events.last)
                        }
                    }
                    .padding()
                    .onAppear {
                        analyticsService.eventDetailsWereViewed(postId: post.id)
                    }
                }
            }
            .background(ColorName.background.color)
        }
        .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, items: ViewState.allCases.compactMap { $0.title })
                    .frame(width: UIDevice.current.userInterfaceIdiom == .pad ? 400 : 285 )
            }
            ToolbarItem(placement: .navigationBarTrailing) {
                ZStack {
                    Button(action: {
                        if let url = post.link {
                            UIActivityViewController.shareSheet(url: url)
                        }
                    }, label: {
                        ImageName.System.share.image
                    })
                }
                .animation(.easeInOut, value: viewState)
            }
            
        }
        .onAppear {
            refreshPost()
            analyticsService.eventWasViewed(postId: post.id)
        }
    }
    
    private func refreshPost() {
        Task {
            do {
                let post = try await contentService.hydratePost(post.id, force: true)
                if post.isHydrated {
                    // TODO: details
                    //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
            } catch {
                //self.comments = []
                self.banner = nil
            }
        }
    }
}


private struct EventSummaryView: View {
    var post: Post
    var event: Post.Event
    var isLast: Bool = false

    @EnvironmentObject private var eventsService: EventsService
    @State private var ekEvent: EKEvent?
    @State private var showExistingSettingsAlert: Bool = false
    
    var body: some View {
        VStack(alignment: .leading, spacing: 9) {
            
            let shouldAddToCalendar = Binding<Bool> {
                ekEvent != nil
            } set: { newValue in
                if !newValue {
                    ekEvent = nil
                }
            }
            
            HStack(alignment: .top, spacing: 13) {
                VStack(alignment: .leading, spacing: 0) {
                    
                    Text(event.longDateString)
                        .textStyle(.subheadline, color: ColorName.text.color(variation: .primary))
                        .multilineTextAlignment(.leading)
                    
                    if let location = event.location {
                        Text(location)
                            .textStyle(.caption1, color: ColorName.text.color(variation: .tertiary))
                            .padding(.top, 10)
                            .fixedSize(horizontal: false, vertical: true)
                            .multilineTextAlignment(.leading)
                    }
                }
                
                Spacer()
                
                VStack(alignment: .leading, spacing: 0) {
                    if let timeStart = event.startTimeString(withPrefix: true) {
                        Text(timeStart)
                            .textStyle(.caption1, color: ColorName.text.color(variation: .secondary))
                    }
                    if let timeEnd = event.endTimeString() {
                        Text(timeEnd)
                            .textStyle(.caption1, color: ColorName.text.color(variation: .tertiary))
                    }
                }
                
                Button {
                    Task {
                        do {
                            try await eventsService.requestPermission()
                        } catch {
                            await MainActor.run {
                                self.showExistingSettingsAlert.toggle()
                            }
                        }
                        
                        do {
                            let ekEvent = try eventsService.createEKEvent(post: post, postEvent: event)
                            
                            await MainActor.run {
                                self.ekEvent = ekEvent
                            }
                        } catch {
                            // Display error
                        }
                    }
                } label: {
                    ImageName.System.addToCalendar.image
                        .textStyle(.title2, color: ColorName.tint.color)
                        .padding(3)
                        
                }
                .sheet(isPresented: shouldAddToCalendar) {
                    AddEventView(event: ekEvent)
                }
                .alert(isPresented: $showExistingSettingsAlert) {
                    Alert(title: Text("Enable Calendar Access"),
                          message: Text("Open settings to enable calendar access for Riotact."),
                          dismissButton: .default(Text("Open Settings"), action: {
                        UIApplication.shared.open(URL(string: UIApplication.openSettingsURLString)!)
                    }))
                }

            }
            
            if !isLast {
                Rectangle()
                    .fill(ColorName.separator.color)
                    .frame(height:1)
            }
        }
        
    }
}
