import HUD
import UIKit
import Shared
import Combine
import Defaults
import PushFeature
import DependencyInjection

public final class LaunchController: UIViewController {
    @Dependency private var hud: HUD
    @Dependency private var coordinator: LaunchCoordinating

    @KeyObject(.acceptedTerms, defaultValue: false) var didAcceptTerms: Bool

    lazy private var screenView = LaunchView()

    private let blocker = UpdateBlocker()
    private let viewModel = LaunchViewModel()
    public var pendingPushRoute: PushRouter.Route?
    private var cancellables = Set<AnyCancellable>()

    public override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        viewModel.viewDidAppear()
    }

    public override func loadView() {
        view = screenView
    }

    public override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        navigationController?
            .navigationBar
            .customize(translucent: true)
    }

    public override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        screenView.setupGradient()
    }

    public override func viewDidLoad() {
        super.viewDidLoad()

        viewModel.hudPublisher
            .receive(on: DispatchQueue.main)
            .sink { [hud] in hud.update(with: $0) }
            .store(in: &cancellables)

        viewModel.routePublisher
            .receive(on: DispatchQueue.main)
            .sink { [unowned self] in
                switch $0 {
                case .chats:
                    guard didAcceptTerms == true else {
                        coordinator.toTerms(from: self)
                        return
                    }

                    if let pushRoute = pendingPushRoute {
                        switch pushRoute {
                        case .requests:
                            coordinator.toRequests(from: self)

                        case .search(username: let username):
                            coordinator.toSearch(searching: username, from: self)

                        case .groupChat(id: let groupId):
                            if let groupInfo = viewModel.getGroupInfoWith(groupId: groupId) {
                                coordinator.toGroupChat(with: groupInfo, from: self)
                                return
                            }
                            coordinator.toChats(from: self)

                        case .contactChat(id: let userId):
                            if let contact = viewModel.getContactWith(userId: userId) {
                                coordinator.toSingleChat(with: contact, from: self)
                                return
                            }
                            coordinator.toChats(from: self)
                        }

                        return
                    }

                    coordinator.toChats(from: self)

                case .onboarding(let ndf):
                    coordinator.toOnboarding(with: ndf, from: self)

                case .update(let model):
                    offerUpdate(model: model)
                }
            }.store(in: &cancellables)
    }

    private func offerUpdate(model: Update) {
        let drawerView = UIView()
        drawerView.backgroundColor = Asset.neutralSecondary.color
        drawerView.layer.cornerRadius = 5

        let vStack = UIStackView()
        vStack.axis = .vertical
        vStack.spacing = 10
        drawerView.addSubview(vStack)

        vStack.snp.makeConstraints {
            $0.top.equalToSuperview().offset(18)
            $0.left.equalToSuperview().offset(18)
            $0.right.equalToSuperview().offset(-18)
            $0.bottom.equalToSuperview().offset(-18)
        }

        let title = UILabel()
        title.text = "App Update"
        title.textAlignment = .center
        title.textColor = Asset.neutralDark.color

        let body = UILabel()
        body.numberOfLines = 0
        body.textAlignment = .center
        body.textColor = Asset.neutralDark.color

        let update = CapsuleButton()
        update.publisher(for: .touchUpInside)
            .sink { UIApplication.shared.open(.init(string: model.urlString)!, options: [:]) }
            .store(in: &cancellables)

        vStack.addArrangedSubview(title)
        vStack.addArrangedSubview(body)
        vStack.addArrangedSubview(update)

        body.text = model.content
        update.set(
            style: model.actionStyle,
            title: model.positiveActionTitle
        )

        if let negativeTitle = model.negativeActionTitle {
            let negativeButton = CapsuleButton()
            negativeButton.set(style: .simplestColoredRed, title: negativeTitle)

            negativeButton.publisher(for: .touchUpInside)
                .sink { [unowned self] in
                    blocker.hideWindow()
                    viewModel.versionApproved()
                }.store(in: &cancellables)

            vStack.addArrangedSubview(negativeButton)
        }

        blocker.window?.addSubview(drawerView)
        drawerView.snp.makeConstraints {
            $0.left.equalToSuperview().offset(18)
            $0.center.equalToSuperview()
            $0.right.equalToSuperview().offset(-18)
        }

        blocker.showWindow()
    }
}