import SwiftUI

struct FeedbackView: View {
    enum InterfaceState: Equatable {
        case idle
        case posting
        case done
        case error(String)
    }
    
    @EnvironmentObject var userService: UserService
    
    @State private var comment: String = ""
    @State private var interfaceState: InterfaceState = .idle
    
    private var guidelineText: String {
        "Thank you for using our app! We are working hard to provide the best experience possible. Please let us know anything that could be improved or features you would like to see in future versions."
    }
    
    private var email: String? {
        guard case .signedIn(let response) = userService.signedInState else {
            return nil
        }
        
        return response.email
    }
    
    private var isFinished: Bool {
        switch interfaceState {
        case .done, .error:
            return true
        default:
            return false
        }
    }
    
    private var finishedImage: Image {
        switch interfaceState {
        case .error:
            return ImageName.System.fail.image
        default:
            return ImageName.System.success.image
        }
    }
    
    private var finishedTitle: String {
        switch interfaceState {
        case .error:
            return "There was an error submitting feedback."
        default:
            return "Thanks for your feedback!"
        }
    }
    
    private var finishedMessage: String? {
        switch interfaceState {
        case .error(let message):
            return "Tap to to try again.\nReason: \(message)"
        default:
            return nil
        }
    }
    
    var body: some View {
        ZStack {
            ProgressView(label: {
                Text("Submitting feedback...")
                    .textStyle(.caption1)
                }
            )
            .progressViewStyle(CircularProgressViewStyle())
            .opacity(interfaceState == .posting ? 1 : 0)
            
            Button {
                comment = ""
                interfaceState = .idle
            } label: {
                VStack(spacing: 10) {
                    finishedImage
                        .textStyle(.largeTitle, color: ColorName.tint.color)
                    
                    Text(finishedTitle)
                        .textStyle(.title2)
                        .multilineTextAlignment(.center)
                    
                    if let finishedMessage = finishedMessage {
                        Text(finishedMessage)
                            .textStyle(.caption1)
                            .multilineTextAlignment(.center)
                    }
                    
                }
            }
            .disabled(!isFinished)
            .opacity(isFinished ? 1 : 0)
            
            VStack {
                Text(guidelineText)
                    .textStyle(.caption1)
                
                TextEditor(text: $comment)
                    .textStyle(.body)
                    .padding(6)
                    .background(
                        RoundedRectangle(cornerRadius: 6)
                            .fill(ColorName.background.color(variation: .secondary))
                    )
                
                Button {
                    submit()
                    
                } label: {
                    Text("Submit")
                }
                .buttonStyle(PrimaryButtonStyle())
                .opacity(comment.isEmpty ? 0.5 : 1)
                .disabled(comment.isEmpty)
                .transition(.opacity)
                .animation(.easeInOut, value: comment.isEmpty)
            }
            .opacity(interfaceState == .idle ? 1 : 0)
        }
        
        .padding()
        .background(ColorName.background.color().ignoresSafeArea())
        .navigationBarTitleDisplayMode(.inline)
        .navigationTitle("Provide Feedback")
    }
    
    private func submit() {
        if comment.isEmpty {
            return
        }
        
        withAnimation {
            interfaceState = .posting
        }
        
        let feedback = Feedback(email: email, message: comment)
        
        Task {
            do {
                try await userService.postFeedback(feedback)
                withAnimation {
                    interfaceState = .done
                }
            } catch {
                withAnimation {
                    interfaceState = .error(error.localizedDescription)
                }
            }
        }
    }
}

#if DEBUG
struct FeedbackView_Previews: PreviewProvider {
    static var previews: some View {
        FeedbackView()
    }
}
#endif
