//
//  LoginViewController.swift
//  suixinkan
//

import SafariServices
import SnapKit
import UIKit

/// 登录页，UI 严格对齐 Android `LoginScreen`。
final class LoginViewController: BaseViewController {

    private let viewModel = LoginViewModel()
    private let authAPI = NetworkServices.shared.authAPI

    private let backgroundImageView = UIImageView()
    private let welcomeLabel = UILabel()
    private let formCardShadowView = UIView()
    private let formCardView = UIView()
    private let topFormStack = UIStackView()
    private let accountField = LoginTextField(placeholder: "请输入账号")
    private let passwordField = PasswordInputField()
    private let agreementRow = AgreementRowView()
    private let loginButton = AppButton(title: "登录", style: .primary)
    private let loginByCodeButton = AppButton(title: "验证码登录", style: .secondary)
    private let registerContainer = UIStackView()
    private let registerPrefixLabel = UILabel()
    private let registerButton = UIButton(type: .system)

    private weak var accountSelectionController: AccountSelectionViewController?

    override var preferredStatusBarStyle: UIStatusBarStyle {
        .lightContent
    }

    override func setupNavigationBar() {
        navigationController?.setNavigationBarHidden(true, animated: false)
    }

    override func setupUI() {
        view.backgroundColor = .black

        backgroundImageView.image = UIImage(named: "img_login_bg")
        backgroundImageView.contentMode = .scaleAspectFill
        backgroundImageView.clipsToBounds = true

        welcomeLabel.text = "欢迎使用\n随心瞰商家版"
        welcomeLabel.numberOfLines = 2
        welcomeLabel.font = .systemFont(ofSize: 28, weight: .semibold)
        welcomeLabel.textColor = .white

        formCardShadowView.backgroundColor = .clear
        formCardShadowView.layer.shadowColor = UIColor.black.cgColor
        formCardShadowView.layer.shadowOpacity = 0.14
        formCardShadowView.layer.shadowOffset = CGSize(width: 0, height: 8)
        formCardShadowView.layer.shadowRadius = 20

        formCardView.backgroundColor = .white
        formCardView.layer.cornerRadius = 16
        formCardView.clipsToBounds = true

        topFormStack.axis = .vertical
        topFormStack.spacing = 0
        topFormStack.alignment = .fill
        topFormStack.distribution = .fill

        loginButton.addTarget(self, action: #selector(loginButtonTapped), for: .touchUpInside)
        loginByCodeButton.addTarget(self, action: #selector(loginByCodeButtonTapped), for: .touchUpInside)

        registerContainer.axis = .horizontal
        registerContainer.alignment = .center
        registerContainer.spacing = 0

        registerPrefixLabel.text = "没有账号？"
        registerPrefixLabel.font = .systemFont(ofSize: 14, weight: .medium)
        registerPrefixLabel.textColor = AppColor.text333

        registerButton.setTitle("去注册", for: .normal)
        registerButton.titleLabel?.font = .systemFont(ofSize: 14, weight: .medium)
        registerButton.setTitleColor(AppColor.primary, for: .normal)
        registerButton.addTarget(self, action: #selector(registerButtonTapped), for: .touchUpInside)

        registerContainer.addArrangedSubview(registerPrefixLabel)
        registerContainer.addArrangedSubview(registerButton)

        view.addSubview(backgroundImageView)
        view.addSubview(welcomeLabel)
        view.addSubview(formCardShadowView)
        formCardShadowView.addSubview(formCardView)
        formCardView.addSubview(topFormStack)
        formCardView.addSubview(registerContainer)

        topFormStack.addArrangedSubview(accountField)
        topFormStack.setCustomSpacing(8, after: accountField)
        topFormStack.addArrangedSubview(passwordField)
        topFormStack.setCustomSpacing(24, after: passwordField)
        topFormStack.addArrangedSubview(agreementRow)
        topFormStack.setCustomSpacing(16, after: agreementRow)
        topFormStack.addArrangedSubview(loginButton)
        topFormStack.setCustomSpacing(8, after: loginButton)
        topFormStack.addArrangedSubview(loginByCodeButton)

        viewModel.applyStoredPreferences()
        if let username = viewModel.normalizedUsername.nonEmpty ?? viewModel.account.nonEmpty {
            accountField.text = username
        }
        agreementRow.isChecked = viewModel.isPrivacyChecked

        bindViewModel()
        updateUI()
    }

    override func setupConstraints() {
        backgroundImageView.snp.makeConstraints { make in
            make.edges.equalToSuperview()
        }

        welcomeLabel.snp.makeConstraints { make in
            make.top.equalTo(view.safeAreaLayoutGuide).offset(50)
            make.leading.trailing.equalTo(view.safeAreaLayoutGuide).inset(24)
        }

        formCardShadowView.snp.makeConstraints { make in
            make.top.equalTo(welcomeLabel.snp.bottom).offset(50)
            make.leading.trailing.equalTo(view.safeAreaLayoutGuide).inset(24)
            make.bottom.lessThanOrEqualTo(view.safeAreaLayoutGuide).offset(-24)
        }

        formCardView.snp.makeConstraints { make in
            make.edges.equalToSuperview()
        }

        registerContainer.snp.makeConstraints { make in
            make.centerX.equalToSuperview()
        }

        applyCardLayoutConstraints(showRegisterSection: false)
    }

    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        formCardShadowView.layer.shadowPath = UIBezierPath(
            roundedRect: formCardShadowView.bounds,
            cornerRadius: 16
        ).cgPath
    }

    override func bindActions() {
        accountField.onTextChange = { [weak self] text in
            self?.viewModel.updateAccount(text)
        }
        accountField.onReturnKey = { [weak self] in
            self?.passwordField.becomeFirstResponder()
        }
        accountField.onEditingDidEnd = { [weak self] in
            self?.viewModel.normalizeUsernameCountryCodeIfNeeded()
            if let username = self?.viewModel.normalizedUsername {
                self?.accountField.text = username
            }
        }

        passwordField.onTextChange = { [weak self] text in
            self?.viewModel.updatePassword(text)
        }
        passwordField.onReturnKey = { [weak self] in
            self?.view.endEditing(true)
            self?.viewModel.login()
        }

        agreementRow.onCheckedChange = { [weak self] in
            self?.viewModel.togglePrivacyChecked()
        }
        agreementRow.onUserAgreementTap = { [weak self] in
            self?.viewModel.onUserAgreement?()
        }
        agreementRow.onPrivacyPolicyTap = { [weak self] in
            self?.viewModel.onPrivacyPolicy?()
        }

        setupDismissKeyboardGesture()
    }

    private func setupDismissKeyboardGesture() {
        let tap = UITapGestureRecognizer(target: self, action: #selector(dismissKeyboard))
        tap.cancelsTouchesInView = false
        tap.delegate = self
        view.addGestureRecognizer(tap)
    }

    @objc private func dismissKeyboard() {
        view.endEditing(true)
    }

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        Task { await viewModel.loadAppConfig(authAPI: authAPI) }
    }

    private func bindViewModel() {
        viewModel.onStateChange = { [weak self] in
            self?.updateUI()
        }
        viewModel.onShowMessage = { [weak self] message in
            self?.showToast(message)
        }
        viewModel.onLogin = { [weak self] in
            self?.performLogin()
        }
        viewModel.onLoginByCode = { [weak self] in
            self?.showToast("验证码登录待接入")
        }
        viewModel.onRegister = { [weak self] in
            self?.showToast("注册待接入")
        }
        viewModel.onUserAgreement = { [weak self] in
            self?.openAgreementURL(AppAgreementURLs.userAgreement)
        }
        viewModel.onPrivacyPolicy = { [weak self] in
            self?.openAgreementURL(AppAgreementURLs.privacyPolicy)
        }
    }

    private func updateUI() {
        agreementRow.isChecked = viewModel.isPrivacyChecked
        loginButton.isEnabled = viewModel.isLoginEnabled && !viewModel.isLoading
        loginButton.alpha = viewModel.isLoading ? 0.7 : 1

        let showRegisterSection = viewModel.enableRegister
        loginByCodeButton.isHidden = !showRegisterSection
        registerContainer.isHidden = !showRegisterSection
        applyCardLayoutConstraints(showRegisterSection: showRegisterSection)

        if let payload = viewModel.pendingAccountSelection {
            if let controller = accountSelectionController {
                controller.updateLoading(viewModel.isSelectingAccount)
            } else if presentedViewController == nil {
                presentAccountSelection(payload)
            }
        } else if accountSelectionController != nil {
            dismiss(animated: true)
            accountSelectionController = nil
        }
    }

    /// 卡片高度随内容自适应，底部与屏幕 safeArea 至少保留 24pt 间距。
    private func applyCardLayoutConstraints(showRegisterSection: Bool) {
        if showRegisterSection {
            topFormStack.snp.remakeConstraints { make in
                make.top.leading.trailing.equalToSuperview().inset(16)
            }
            registerContainer.snp.remakeConstraints { make in
                make.top.equalTo(topFormStack.snp.bottom).offset(16)
                make.centerX.equalToSuperview()
                make.bottom.equalToSuperview().inset(16)
            }
        } else {
            registerContainer.snp.remakeConstraints { make in
                make.centerX.equalToSuperview()
            }
            topFormStack.snp.remakeConstraints { make in
                make.edges.equalToSuperview().inset(16)
            }
        }
    }

    private func performLogin() {
        viewModel.normalizeUsernameCountryCodeIfNeeded()
        accountField.text = viewModel.normalizedUsername

        Task {
            showLoading()
            defer { hideLoading() }

            do {
                let resolution = try await viewModel.login(authAPI: authAPI)
                switch resolution {
                case let .completed(response, account):
                    completeLogin(with: response, account: account)
                case .needsAccountSelection:
                    break
                }
            } catch is CancellationError {
                return
            } catch {
                showToast(error.localizedDescription)
            }
        }
    }

    private func presentAccountSelection(_ payload: AccountSelectionPayload) {
        let controller = AccountSelectionViewController(
            payload: payload,
            isLoading: viewModel.isSelectingAccount,
            onCancel: { [weak self] in
                self?.viewModel.clearPendingAccountSelection()
                self?.accountSelectionController = nil
            },
            onConfirm: { [weak self] account in
                self?.selectAccount(account)
            }
        )
        accountSelectionController = controller
        let navigation = UINavigationController(rootViewController: controller)
        navigation.modalPresentationStyle = .formSheet
        present(navigation, animated: true)
    }

    private func selectAccount(_ account: AccountSwitchAccount) {
        Task {
            accountSelectionController?.updateLoading(true)
            defer { accountSelectionController?.updateLoading(false) }

            do {
                let response = try await viewModel.selectAccount(account, authAPI: authAPI)
                completeLogin(with: response, account: account)
                accountSelectionController = nil
                dismiss(animated: true)
            } catch is CancellationError {
                return
            } catch {
                showToast(error.localizedDescription)
            }
        }
    }

    private func completeLogin(with response: V9AuthResponse, account: AccountSwitchAccount) {
        AuthSessionHelper.completeLogin(
            with: response,
            username: viewModel.normalizedUsername,
            privacyAgreementAccepted: viewModel.isPrivacyChecked,
            selectedAccount: account
        )
    }

    @objc private func loginButtonTapped() {
        view.endEditing(true)
        viewModel.login()
    }

    @objc private func loginByCodeButtonTapped() {
        view.endEditing(true)
        viewModel.onLoginByCode?()
    }

    @objc private func registerButtonTapped() {
        view.endEditing(true)
        viewModel.onRegister?()
    }

    private func openAgreementURL(_ url: URL) {
        let controller = SFSafariViewController(url: url)
        present(controller, animated: true)
    }
}

extension LoginViewController: UIGestureRecognizerDelegate {
    /// 点击输入框、按钮时不触发收键盘，避免干扰正常交互。
    func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
        var candidate: UIView? = touch.view
        while let view = candidate {
            if view is UITextField || view is UIButton {
                return false
            }
            candidate = view.superview
        }
        return true
    }
}

private extension String {
    var nonEmpty: String? {
        let text = trimmingCharacters(in: .whitespacesAndNewlines)
        return text.isEmpty ? nil : text
    }
}
