import Shared
import Models
import Combine
import XXClient
import Countries
import InputField
import Foundation
import CombineSchedulers
import XXMessengerClient
import DependencyInjection

struct OnboardingPhoneViewState: Equatable {
  var input: String = ""
  var confirmation: AttributeConfirmation?
  var status: InputField.ValidationStatus = .unknown(nil)
  var country: Country = .fromMyPhone()
}

final class OnboardingPhoneViewModel {
  @Dependency var messenger: Messenger
  @Dependency var hudController: HUDController
  
  var state: AnyPublisher<OnboardingPhoneViewState, Never> { stateRelay.eraseToAnyPublisher() }
  private let stateRelay = CurrentValueSubject<OnboardingPhoneViewState, Never>(.init())
  
  var backgroundScheduler: AnySchedulerOf<DispatchQueue> = DispatchQueue.global().eraseToAnyScheduler()

  func clearUp() {
    stateRelay.value.confirmation = nil
  }
  
  func didInput(_ string: String) {
    stateRelay.value.input = string
    validate()
  }
  
  func didChooseCountry(_ country: Country) {
    stateRelay.value.country = country
    validate()
  }
  
  func didGoForward() {
    stateRelay.value.confirmation = nil
  }
  
  func didTapNext() {
    hudController.show()
    
    backgroundScheduler.schedule { [weak self] in
      guard let self = self else { return }
      
      let content = "\(self.stateRelay.value.input)\(self.stateRelay.value.country.code)"
      
      do {
        let confirmationId = try self.messenger.ud.get()!.sendRegisterFact(
          .init(type: .phone, value: content)
        )
        
        self.hudController.dismiss()
        self.stateRelay.value.confirmation = .init(
          content: content,
          confirmationId: confirmationId
        )
      } catch {
        let xxError = CreateUserFriendlyErrorMessage.live(error.localizedDescription)
        self.hudController.show(.init(content: xxError))
      }
    }
  }
  
  private func validate() {
    switch Validator.phone.validate((stateRelay.value.country.regex, stateRelay.value.input)) {
    case .success:
      stateRelay.value.status = .valid(nil)
    case .failure(let error):
      stateRelay.value.status = .invalid(error)
    }
  }
}