import UIKit
import Shared
import Combine
import DrawerFeature
import DependencyInjection

public final class ProfileController: UIViewController {
  @Dependency var barStylist: StatusBarStylist
  @Dependency var coordinator: ProfileCoordinating

  lazy private var screenView = ProfileView()

  private let viewModel = ProfileViewModel()
  private var cancellables = Set<AnyCancellable>()
  private var drawerCancellables = Set<AnyCancellable>()

  public override func loadView() {
    view = screenView
  }

  public override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    barStylist.styleSubject.send(.lightContent)
    navigationController?.navigationBar
      .customize(backgroundColor: Asset.neutralBody.color)
    viewModel.refresh()
  }

  public override func viewDidLoad() {
    super.viewDidLoad()
    screenView.cardComponent.nameLabel.text = viewModel.username!
    setupNavigationBar()
    setupBindings()
  }

  private func setupNavigationBar() {
    navigationItem.backButtonTitle = ""

    let menuButton = UIButton()
    menuButton.tintColor = Asset.neutralWhite.color
    menuButton.setImage(Asset.chatListMenu.image, for: .normal)
    menuButton.addTarget(self, action: #selector(didTapMenu), for: .touchUpInside)
    menuButton.snp.makeConstraints { $0.width.equalTo(50) }

    navigationItem.leftBarButtonItem = UIBarButtonItem(customView: menuButton)
  }

  private func setupBindings() {
    screenView.emailView.actionButton
      .publisher(for: .touchUpInside)
      .receive(on: DispatchQueue.main)
      .sink { [unowned self] in
        if screenView.emailView.currentValue != nil {
          presentDrawer(
            title: Localized.Profile.Delete.title(
              Localized.Profile.Email.title.capitalized
            ),
            subtitle: Localized.Profile.Delete.subtitle(
              Localized.Profile.Email.title.lowercased(), Localized.Profile.Email.title.lowercased()
            ),
            actionTitle: Localized.Profile.Delete.action(
              Localized.Profile.Email.title
            )) {
              self.viewModel.didTapDelete(isEmail: true)
            }
        } else {
          coordinator.toEmail(from: self)
        }
      }.store(in: &cancellables)

    screenView.phoneView.actionButton
      .publisher(for: .touchUpInside)
      .receive(on: DispatchQueue.main)
      .sink { [unowned self] in
        if screenView.phoneView.currentValue != nil {
          presentDrawer(
            title: Localized.Profile.Delete.title(
              Localized.Profile.Phone.title.capitalized
            ),
            subtitle: Localized.Profile.Delete.subtitle(
              Localized.Profile.Phone.title.lowercased(), Localized.Profile.Phone.title.lowercased()
            ),
            actionTitle: Localized.Profile.Delete.action(
              Localized.Profile.Phone.title
            )) {
              self.viewModel.didTapDelete(isEmail: false)
            }
        } else {
          coordinator.toPhone(from: self)
        }
      }.store(in: &cancellables)

    screenView.cardComponent.avatarView.editButton
      .publisher(for: .touchUpInside)
      .receive(on: DispatchQueue.main)
      .sink { [unowned self] in viewModel.didRequestLibraryAccess() }
      .store(in: &cancellables)

    viewModel.navigation
      .receive(on: DispatchQueue.main)
      .removeDuplicates()
      .sink { [unowned self] in
        switch $0 {
        case .library:
          presentDrawer(
            title: Localized.Profile.Photo.title,
            subtitle: Localized.Profile.Photo.subtitle,
            actionTitle: Localized.Profile.Photo.continue) {
              self.coordinator.toPhotos(from: self)
            }
        case .libraryPermission:
          coordinator.toPermission(type: .library, from: self)
        case .none:
          break
        }

        viewModel.didNavigateSomewhere()
      }.store(in: &cancellables)

    viewModel.state
      .map(\.email)
      .removeDuplicates()
      .receive(on: DispatchQueue.main)
      .sink { [unowned self] in screenView.emailView.set(value: $0) }
      .store(in: &cancellables)

    viewModel.state
      .map(\.phone)
      .removeDuplicates()
      .receive(on: DispatchQueue.main)
      .sink { [unowned self] in screenView.phoneView.set(value: $0) }
      .store(in: &cancellables)

    viewModel.state
      .map(\.photo)
      .compactMap { $0 }
      .removeDuplicates()
      .receive(on: DispatchQueue.main)
      .sink { [unowned self] in screenView.cardComponent.image = $0 }
      .store(in: &cancellables)
  }

  private func presentDrawer(
    title: String,
    subtitle: String,
    actionTitle: String,
    action: @escaping () -> Void
  ) {
    let actionButton = DrawerCapsuleButton(model: .init(
      title: actionTitle,
      style: .red
    ))

    let drawer = DrawerController(with: [
      DrawerText(
        font: Fonts.Mulish.bold.font(size: 26.0),
        text: title,
        color: Asset.neutralActive.color,
        alignment: .left,
        spacingAfter: 19
      ),
      DrawerText(
        font: Fonts.Mulish.regular.font(size: 16.0),
        text: subtitle,
        color: Asset.neutralBody.color,
        alignment: .left,
        lineHeightMultiple: 1.1,
        spacingAfter: 37
      ),
      actionButton
    ])

    actionButton.action
      .receive(on: DispatchQueue.main)
      .sink {
        drawer.dismiss(animated: true) { [weak self] in
          guard let self = self else { return }
          self.drawerCancellables.removeAll()

          action()
        }
      }.store(in: &drawerCancellables)

    coordinator.toDrawer(drawer, from: self)
  }

  @objc private func didTapMenu() {
    coordinator.toSideMenu(from: self)
  }
}

extension ProfileController: UIImagePickerControllerDelegate {
  public func imagePickerController(
    _ picker: UIImagePickerController,
    didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]
  ) {
    var image: UIImage?

    if let originalImage = info[.originalImage] as? UIImage {
      image = originalImage
    }

    if let croppedImage = info[.editedImage] as? UIImage {
      image = croppedImage
    }

    guard let image = image else {
      picker.dismiss(animated: true)
      return
    }

    picker.dismiss(animated: true)
    viewModel.didChoosePhoto(image)
  }
}

extension ProfileController: UINavigationControllerDelegate {}