//
// Created by Avently on 16.01.2023.
// Copyright (c) 2023 SimpleX Chat. All rights reserved.
//

import SwiftUI
import SimpleXChat

struct UserPicker: View {
    @EnvironmentObject var m: ChatModel
    @Environment(\.scenePhase) var scenePhase
    @EnvironmentObject var theme: AppTheme
    @Binding var showSettings: Bool
    @Binding var showConnectDesktop: Bool
    @Binding var userPickerVisible: Bool
    @State var scrollViewContentSize: CGSize = .zero
    @State var disableScrolling: Bool = true
    private let menuButtonHeight: CGFloat = 68
    @State var chatViewNameWidth: CGFloat = 0


    var body: some View {
        VStack {
            Spacer().frame(height: 1)
            VStack(spacing: 0) {
                ScrollView {
                    ScrollViewReader { sp in
                        let users = m.users
                                    .filter({ u in u.user.activeUser || !u.user.hidden })
                                    .sorted { u, _ in u.user.activeUser }
                        VStack(spacing: 0) {
                            ForEach(users) { u in
                                userView(u)
                                Divider()
                                if u.user.activeUser { Divider() }
                            }
                        }
                        .overlay {
                            GeometryReader { geo -> Color in
                                DispatchQueue.main.async {
                                    scrollViewContentSize = geo.size
                                    let scenes = UIApplication.shared.connectedScenes
                                    if let windowScene = scenes.first as? UIWindowScene {
                                        let layoutFrame = windowScene.windows[0].safeAreaLayoutGuide.layoutFrame
                                        disableScrolling = scrollViewContentSize.height + menuButtonHeight + 10 < layoutFrame.height
                                    }
                                }
                                return Color.clear
                            }
                        }
                        .onChange(of: userPickerVisible) { visible in
                            if visible, let u = users.first {
                                sp.scrollTo(u.id)
                            }
                        }
                    }
                }
                .simultaneousGesture(DragGesture(minimumDistance: disableScrolling ? 0 : 10000000))
                .frame(maxHeight: scrollViewContentSize.height)

                menuButton("Use from desktop", icon: "desktopcomputer") {
                    showConnectDesktop = true
                    withAnimation {
                        userPickerVisible.toggle()
                    }
                }
                Divider()
                menuButton("Settings", icon: "gearshape") {
                    showSettings = true
                    withAnimation {
                        userPickerVisible.toggle()
                    }
                }
            }
        }
        .clipShape(RoundedRectangle(cornerRadius: 16))
        .background(
            Rectangle()
                .fill(theme.colors.surface)
                .cornerRadius(16)
                .shadow(color: .black.opacity(0.12), radius: 24, x: 0, y: 0)
        )
        .onPreferenceChange(DetermineWidth.Key.self) { chatViewNameWidth = $0 }
        .frame(maxWidth: chatViewNameWidth > 0 ? min(300, chatViewNameWidth + 130) : 300)
        .padding(8)
        .opacity(userPickerVisible ? 1.0 : 0.0)
        .onAppear {
             // This check prevents the call of listUsers after the app is suspended, and the database is closed.
             if case .active = scenePhase {
                 Task {
                     do {
                         let users = try await listUsersAsync()
                         await MainActor.run { m.users = users }
                     } catch {
                         logger.error("Error loading users \(responseError(error))")
                     }
                 }
             }
         }
    }

    private func userView(_ u: UserInfo) -> some View {
        let user = u.user
        return Button(action: {
            if user.activeUser {
                showSettings = true
                withAnimation {
                    userPickerVisible.toggle()
                }
            } else {
                Task {
                    do {
                        try await changeActiveUserAsync_(user.userId, viewPwd: nil)
                        await MainActor.run { userPickerVisible = false }
                    } catch {
                        await MainActor.run {
                            AlertManager.shared.showAlertMsg(
                                title: "Error switching profile!",
                                message: "Error: \(responseError(error))"
                            )
                        }
                    }
                }
            }
        }, label: {
            HStack(spacing: 0) {
                ProfileImage(imageStr: user.image, size: 44, color: Color(uiColor: .tertiarySystemFill))
                    .padding(.trailing, 12)
                Text(user.chatViewName)
                    .fontWeight(user.activeUser ? .medium : .regular)
                    .foregroundColor(theme.colors.onBackground)
                    .overlay(DetermineWidth())
                Spacer()
                if user.activeUser {
                    Image(systemName: "checkmark")
                } else if u.unreadCount > 0 {
                    unreadCounter(u.unreadCount, color: user.showNtfs ? theme.colors.primary : theme.colors.secondary)
                } else if !user.showNtfs {
                    Image(systemName: "speaker.slash")
                }
            }
            .padding(.trailing)
            .padding([.leading, .vertical], 12)
        })
        .buttonStyle(PressedButtonStyle(defaultColor: theme.colors.surface, pressedColor: Color(uiColor: .secondarySystemFill)))
    }

    private func menuButton(_ title: LocalizedStringKey, icon: String, action: @escaping () -> Void) -> some View {
        Button(action: action) {
            HStack(spacing: 0) {
                Text(title)
                    .overlay(DetermineWidth())
                Spacer()
                Image(systemName: icon)
                    .symbolRenderingMode(.monochrome)
                    .foregroundColor(theme.colors.secondary)
            }
            .padding(.horizontal)
            .padding(.vertical, 22)
            .frame(height: menuButtonHeight)
        }
        .buttonStyle(PressedButtonStyle(defaultColor: theme.colors.surface, pressedColor: Color(uiColor: .secondarySystemFill)))
    }
}

private func unreadCounter(_ unread: Int, color: Color) -> some View {
    unreadCountText(unread)
    .font(.caption)
    .foregroundColor(.white)
    .padding(.horizontal, 4)
    .frame(minWidth: 18, minHeight: 18)
    .background(color)
    .cornerRadius(10)
}

struct UserPicker_Previews: PreviewProvider {
    static var previews: some View {
        let m = ChatModel()
        m.users = [UserInfo.sampleData, UserInfo.sampleData]
        return UserPicker(
            showSettings: Binding.constant(false),
            showConnectDesktop: Binding.constant(false),
            userPickerVisible: Binding.constant(true)
        )
        .environmentObject(m)
    }
}
