import SwiftUI
import PhotosUI

struct AlertMessage: Equatable {
    var title: String
    var message: String
}

struct ProfileView: View {
    @EnvironmentObject private var userService: UserService
    @EnvironmentObject private var contentService: ContentService
    
    @State private var postcode: Int = 2600
    @State private var alertMessage: AlertMessage? = nil

    var body: some View {
        let alertBinding = Binding<Bool> {
            alertMessage != nil
        } set: { newValue in
            if !newValue {
                alertMessage = nil
            }
        }
        
        List {
            Section {
                if case .signedIn = userService.signedInState {
                    NameView()
                } else {
                    HStack {
                        Spacer()
                        VStack(alignment: .center, spacing: 26) {
                            Text("Sign in or sign up to make comments and follow the conversation.")
                                .textStyle(.subheadline)
                                .multilineTextAlignment(.center)
                            
                            Button {
                                userService.signInWithViewController()
                            } label: {
                                Text("Sign In")
                            }
                            .buttonStyle(PrimaryButtonStyle())
                        }
                        Spacer()
                    }
                }
            }
            .padding(.vertical)
            .listRowBackground(ColorName.background.color)
            
            //if case .signedIn = userService.signedInState {
                NavigationLink {
                    BookmarksView()
                } label: {
                    SettingsRow(title: "Bookmarks",
                                subtitle: nil)
                    .padding(.vertical, 13)
                }
                .buttonStyle(FlatButtonStyle())
            //}
            
            
            Section {
                NavigationLink {
                    NotificationSettingsView()
                } label: {
                    SettingsRow(title: "Notifications and Alerts",
                                subtitle: "Manage your notification and alert preferences")
                    .padding(.vertical, 13)
                }
                .buttonStyle(FlatButtonStyle())
                
                IntFieldRow(title: "Your Postcode",
                            value: $postcode,
                            numberFormatter: NumberFormatter.postcodeFormatter,
                            onSubmit: { newValue in
                    
                    guard (2600...2999).contains(newValue) else {
                        alertMessage = AlertMessage(title: "Alert", message: "Please enter a valid ACT postcode.")
                        return false
                    }
                    
                    userService.userPostcode = newValue
                    
                    return true
                })
                .padding(.vertical, 13)
                
                ForEach(contentService.policyPages, id: \.self) { page in
                    NavigationLink {
                        PolicyView(policyPage: page)
                    } label: {
                        SettingsRow(title: page.navigationTitle)
                    }
                    .buttonStyle(FlatButtonStyle())
                    .padding(.vertical, 13)
                }
                
                NavigationLink {
                    FeedbackView()
                } label: {
                    SettingsRow(title: "Provide Feedback")
                }
                .buttonStyle(FlatButtonStyle())
                .padding(.vertical, 13)
                
                NavigationLink {
                    DiagnosticsView()
                } label: {
                    SettingsRow(title: "Diagnostics")
                }
                .buttonStyle(FlatButtonStyle())
                .padding(.vertical, 13)
                
                if case .signedIn = userService.signedInState {
                    NavigationLink {
                        DeleteAccountView()
                    } label: {
                        SettingsRow(title: "Account Deletion")
                    }
                    .buttonStyle(FlatButtonStyle())
                    .padding(.vertical, 13)
                }
            }
            .listRowBackground(ColorName.background.color)
        }
        .listStyle(.plain)
        .background(ColorName.background.color(variation: .primary).ignoresSafeArea())
        .onAppear {
            postcode = userService.userPostcode
            Task {
                await userService.updateNotificationSettings()
            }
        }
        .toolbar {
            ToolbarItem(placement: .navigationBarTrailing) {
                SignInOutButton()
            }
        }
        .alert(isPresented: alertBinding) {
            Alert(title: Text(alertMessage?.title ?? ""),
                  message: Text(alertMessage?.message ?? ""),
                  dismissButton: .default(Text("Okay"), action: {
                alertMessage = nil
            }))
        }
    }
}

struct SettingsRow: View {
    var title: String
    var subtitle: String? = nil
    
    var body: some View {
        HStack(alignment: .center) {
            VStack(alignment: .leading, spacing: 2) {
                Text(title)
                    .textStyle(.headline)
                    .multilineTextAlignment(.leading)
                
                if let subtitle = subtitle {
                    Text(subtitle)
                        .textStyle(.subheadline)
                        .multilineTextAlignment(.leading)
                }
            }
            
            Spacer()
            
        }
    }
}

struct IntFieldRow: View {
    var title: String
    @Binding var value: Int
    var numberFormatter: NumberFormatter
    var onSubmit: (Int) -> Bool
    
    @State private var internalValue: Int = 0
    
    var body: some View {
        HStack(alignment: .center) {
                Text(title)
                    .textStyle(.headline)
                    .multilineTextAlignment(.leading)
            
            Spacer()
            
            TextField(title, value: $internalValue, formatter: numberFormatter, onCommit: {
                if onSubmit(internalValue) {
                    value = internalValue
                }
            })
            .keyboardType(.numbersAndPunctuation)
            
            .textStyle(.headline, color: ColorName.tint.color)
            .multilineTextAlignment(.trailing)
            .padding(.horizontal, 6)
        }
        .onAppear {
            internalValue = value
        }
    }
}

struct NameView: View {
    @EnvironmentObject private var contentService: ContentService
    
    var name: String {
        switch contentService.signedInState {
        case .signedIn(response: let response):
            return response.name
            
        default:
            return "Anonymous user"
        }
    }
    
    var email: String? {
        switch contentService.signedInState {
        case .signedIn(response: let response):
            return response.email
            
        default:
            return nil
        }
    }
    
    var deletionStatus: String? {
        guard case .signedIn(response: let response) = contentService.signedInState else {
            return nil
        }
        return response.deleteStatus?.title
    }
    
    var color: Color {
        switch contentService.signedInState {
        case .signedIn:
            return ColorName.text.color
            
        default:
            return ColorName.text.color(variation: .tertiary)
        }
    }
    
    var body: some View {
        HStack(spacing: 13) {
            UserAvatarView()
                .frame(width: 70, height: 70)
            
            VStack(alignment: .leading, spacing: 0) {
                Text(name)
                    .textStyle(.title3)
                    .multilineTextAlignment(.leading)
                    .lineLimit(nil)
                if let email = email {
                    Text(email)
                        .textStyle(.subheadline)
                        .multilineTextAlignment(.leading)
                        .lineLimit(nil)
                }
                if let deletionStatus = deletionStatus {
                    Text(deletionStatus)
                        .textStyle(.subheadline, color: ColorName.text.color(variation: .tertiary))
                        .multilineTextAlignment(.leading)
                        .lineLimit(nil)
                        .padding(.top, 10)
                }
            }
            Spacer()
        }
        
    }
}

struct SignInOutButton: View {
    @EnvironmentObject private var userService: UserService
    
    var body: some View {
        switch userService.signedInState {
        case .unknown, .signedOut, .error:
            EmptyView()
        case .signedIn(_):
            Button(action: { userService.signOut() }) {
                Text("Sign Out")
                    .textStyle(.headline, color: ColorName.tint.color)
            }
        }
    }
    
}

struct PushTokenView: View {
    @EnvironmentObject private var userService: UserService

    var body: some View {
        if let token = userService.token {
            Text(token)
                .textStyle(.caption2)
                .gesture(
                    TapGesture()
                        .onEnded({
                            UIPasteboard.general.string = token
                        })
                )
        }
    }
}

#if DEBUG
struct ProfileView_Previews: PreviewProvider {
    static var previews: some View {
        ProfileView().environmentObject(ContentService.preview)
    }
}
#endif
