import HUD
import UIKit
import Shared
import Models
import Combine
import Defaults
import Countries
import Foundation
import Permissions
import XXClient
import CombineSchedulers
import DependencyInjection

enum ProfileNavigationRoutes {
    case none
    case library
    case libraryPermission
}

struct ProfileViewState: Equatable {
    var email: String?
    var phone: String?
    var photo: UIImage?
}

final class ProfileViewModel {
    @KeyObject(.avatar, defaultValue: nil) var avatar: Data?
    @KeyObject(.email, defaultValue: nil) var emailStored: String?
    @KeyObject(.phone, defaultValue: nil) var phoneStored: String?
    @KeyObject(.username, defaultValue: nil) var username: String?
    @KeyObject(.sharingEmail, defaultValue: false) var isEmailSharing: Bool
    @KeyObject(.sharingPhone, defaultValue: false) var isPhoneSharing: Bool

    @Dependency var userDiscovery: UserDiscovery
    @Dependency private var permissions: PermissionHandling

    var name: String { username! }

    var state: AnyPublisher<ProfileViewState, Never> { stateRelay.eraseToAnyPublisher() }
    private let stateRelay = CurrentValueSubject<ProfileViewState, Never>(.init())

    var hud: AnyPublisher<HUDStatus, Never> { hudRelay.eraseToAnyPublisher() }
    private let hudRelay = CurrentValueSubject<HUDStatus, Never>(.none)

    var navigation: AnyPublisher<ProfileNavigationRoutes, Never> { navigationRoutes.eraseToAnyPublisher() }
    private let navigationRoutes = PassthroughSubject<ProfileNavigationRoutes, Never>()

    var backgroundScheduler: AnySchedulerOf<DispatchQueue> = DispatchQueue.global().eraseToAnyScheduler()

    init() {
        refresh()
    }

    func refresh() {
        var cleanPhone = phoneStored

        if let phone = cleanPhone {
            let country = Country.findFrom(phone)
            cleanPhone = "\(country.prefix)\(phone.dropLast(2))"
        }

        stateRelay.value = .init(
            email: emailStored,
            phone: cleanPhone,
            photo: avatar != nil ? UIImage(data: avatar!) : nil
        )
    }

    func didRequestLibraryAccess() {
        if permissions.isPhotosAllowed {
            navigationRoutes.send(.library)
        } else {
            navigationRoutes.send(.libraryPermission)
        }
    }

    func didNavigateSomewhere() {
        navigationRoutes.send(.none)
    }

    func didChoosePhoto(_ photo: UIImage) {
        stateRelay.value.photo = photo
        avatar = photo.jpegData(compressionQuality: 0.0)
    }

    func didTapDelete(isEmail: Bool) {
        hudRelay.send(.on)

        backgroundScheduler.schedule { [weak self] in
            guard let self = self else { return }

            do {
                try self.userDiscovery.removeFact(
                    .init(
                        fact: isEmail ? "E\(self.emailStored!)" : "P\(self.phoneStored!)",
                        type: isEmail ? FactType.email.rawValue : FactType.phone.rawValue
                    )
                )

                if isEmail {
                    self.emailStored = nil
                    self.isEmailSharing = false
                } else {
                    self.phoneStored = nil
                    self.isPhoneSharing = false
                }

                self.hudRelay.send(.none)
                self.refresh()
            } catch {
                self.hudRelay.send(.error(.init(with: error)))
            }
        }
    }
}