import UIKit
import WebKit

/// SDK 内置容器 ViewController。
///
/// **不要由客户直接 init**;走 ``TencentQianWebView/open(from:url:config:callbacks:)`` 入口。
public final class TencentQianWebViewController: UIViewController {

    // MARK: - 公共

    public let url: String
    public let config: TencentQianWebViewConfig
    public let callbacks: SignCallbacks

    // MARK: - UI

    private let webView: WKWebView
    private var topBar: UIView!
    private var titleLabel: UILabel!
    private var backButton: UIButton!
    private var closeButton: UIButton!
    private var progressBar: UIProgressView!

    // MARK: - SDK Handle(配置模式注入到内部 webView)

    private var handle: TencentQianWebViewConfigurator.Handle?
    private var progressKVO: NSKeyValueObservation?

    public init(url: String, config: TencentQianWebViewConfig, callbacks: SignCallbacks) {
        self.url = url
        self.config = config
        self.callbacks = callbacks
        // 页面容器每次新建独立 WKWebView（不复用预热实例）。
        // 原因：iOS WKWebView 无 clear-history API，复用加载过 warmup.html 的预热实例会导致
        // warmup.html 残留在 backForwardList 中（返回键退回 warmup 页）且无法清除。
        // 预热收益仍通过共享 processPool（进程复用）+ 共享 .default() DataStore（磁盘缓存跨实例命中）承接。
        let webViewConfig = WKConfigurationFactory.makeConfiguration(config)
        self.webView = WKWebView(frame: .zero, configuration: webViewConfig)
        super.init(nibName: nil, bundle: nil)
        self.modalPresentationStyle = .fullScreen
    }

    @available(*, unavailable)
    required init?(coder: NSCoder) {
        fatalError("init(coder:) is not supported")
    }

    public override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = ColorCompat.background
        setupTopBar()
        setupWebView()
        setupProgressBar()

        // 复用 Configurator 注入逻辑(避免重复)
        let bridgedCallbacks = SignCallbacks(
            onSignResult: { [weak self] result in
                self?.callbacks.onSignResult?(result)
                // 协议回调到达后,容器自动关闭
                self?.dismissSelf(animated: true)
            },
            onEvent: { [weak self] event in
                self?.handleEvent(event)
                self?.callbacks.onEvent?(event)
            }
        )
        handle = TencentQianWebViewConfigurator.apply(
            webView: webView,
            hostController: self,
            config: config,
            callbacks: bridgedCallbacks
        )

        if let u = URL(string: url) {
            handle?.load(u)
        } else {
            // 非法 URL 直接关
            dismiss(animated: true)
        }
    }

    public override var preferredStatusBarStyle: UIStatusBarStyle {
        switch config.statusBarStyle {
        case .lightContent: return .lightContent
        case .darkContent:
            if #available(iOS 13, *) { return .darkContent }
            return .default
        }
    }

    public override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        // 注意:不在此处 invalidate progressKVO。
        // 原因:iOS 交互式 pop 手势(从左边缘滑动)开始时就会触发 viewWillDisappear,
        // 如果用户取消手势(滑到一半松手),页面回来后 KVO 已失效,进度条不再更新。
        // KVO 的清理统一在 deinit 中执行。
    }

    public override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        handle?.attemptBlankRecoveryIfNeeded()
    }

    public override func viewDidDisappear(_ animated: Bool) {
        super.viewDidDisappear(animated)
        if isBeingDismissed || isMovingFromParent {
            handle?.detachAndDestroy()
            handle = nil
        }
    }

    deinit {
        progressKVO?.invalidate()
    }

    // MARK: - UI 搭建

    private func setupTopBar() {
        let bar = UIView()
        bar.backgroundColor = config.topBarBackgroundColor ?? ColorCompat.background
        bar.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(bar)
        topBar = bar

        let title = UILabel()
        title.text = config.topBarTitle.isEmpty ? L10n.defaultTitle : config.topBarTitle
        title.textColor = config.topBarTextColor ?? ColorCompat.label
        title.font = .systemFont(ofSize: 17, weight: .semibold)
        title.textAlignment = .center
        title.translatesAutoresizingMaskIntoConstraints = false
        bar.addSubview(title)
        titleLabel = title

        let back = UIButton(type: .system)
        if #available(iOS 13, *) {
            back.setImage(UIImage(systemName: "chevron.left"), for: .normal)
        } else {
            back.setTitle("‹", for: .normal)
            back.titleLabel?.font = .systemFont(ofSize: 28)
        }
        back.tintColor = config.topBarTextColor ?? ColorCompat.label
        back.addTarget(self, action: #selector(onBack), for: .touchUpInside)
        back.translatesAutoresizingMaskIntoConstraints = false
        bar.addSubview(back)
        backButton = back

        let close = UIButton(type: .system)
        if #available(iOS 13, *) {
            close.setImage(UIImage(systemName: "xmark"), for: .normal)
        } else {
            close.setTitle("✕", for: .normal)
            close.titleLabel?.font = .systemFont(ofSize: 20)
        }
        close.tintColor = config.topBarTextColor ?? ColorCompat.label
        close.isHidden = !config.showCloseButton
        close.addTarget(self, action: #selector(onClose), for: .touchUpInside)
        close.translatesAutoresizingMaskIntoConstraints = false
        bar.addSubview(close)
        closeButton = close

        bar.isHidden = !config.showTopBar

        NSLayoutConstraint.activate([
            bar.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
            bar.leadingAnchor.constraint(equalTo: view.leadingAnchor),
            bar.trailingAnchor.constraint(equalTo: view.trailingAnchor),
            bar.heightAnchor.constraint(equalToConstant: 44),

            back.leadingAnchor.constraint(equalTo: bar.leadingAnchor, constant: 8),
            back.centerYAnchor.constraint(equalTo: bar.centerYAnchor),
            back.widthAnchor.constraint(equalToConstant: 44),
            back.heightAnchor.constraint(equalToConstant: 44),

            close.trailingAnchor.constraint(equalTo: bar.trailingAnchor, constant: -8),
            close.centerYAnchor.constraint(equalTo: bar.centerYAnchor),
            close.widthAnchor.constraint(equalToConstant: 44),
            close.heightAnchor.constraint(equalToConstant: 44),

            title.leadingAnchor.constraint(equalTo: back.trailingAnchor, constant: 8),
            title.trailingAnchor.constraint(equalTo: close.leadingAnchor, constant: -8),
            title.centerYAnchor.constraint(equalTo: bar.centerYAnchor)
        ])
    }

    private func setupWebView() {
        webView.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(webView)

        let topAnchor: NSLayoutYAxisAnchor = config.showTopBar ? topBar.bottomAnchor : view.safeAreaLayoutGuide.topAnchor
        NSLayoutConstraint.activate([
            webView.topAnchor.constraint(equalTo: topAnchor),
            webView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
            webView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
            webView.bottomAnchor.constraint(equalTo: view.bottomAnchor)
        ])
    }

    private func setupProgressBar() {
        let pb = UIProgressView(progressViewStyle: .default)
        pb.translatesAutoresizingMaskIntoConstraints = false
        pb.alpha = 0
        view.addSubview(pb)
        progressBar = pb

        let topAnchor: NSLayoutYAxisAnchor = config.showTopBar ? topBar.bottomAnchor : view.safeAreaLayoutGuide.topAnchor
        NSLayoutConstraint.activate([
            pb.topAnchor.constraint(equalTo: topAnchor),
            pb.leadingAnchor.constraint(equalTo: view.leadingAnchor),
            pb.trailingAnchor.constraint(equalTo: view.trailingAnchor),
            pb.heightAnchor.constraint(equalToConstant: 2)
        ])

        progressKVO = webView.observe(\.estimatedProgress, options: [.new]) { [weak self] wv, _ in
            guard let self = self else { return }
            self.progressBar.progress = Float(wv.estimatedProgress)
            UIView.animate(withDuration: 0.2) {
                self.progressBar.alpha = wv.estimatedProgress >= 1.0 ? 0 : 1
            }
        }
    }

    // MARK: - 顶栏按钮

    @objc private func onBack() {
        if webView.canGoBack {
            webView.goBack()
        } else {
            attemptCloseWithConfirm()
        }
    }

    @objc private func onClose() {
        attemptCloseWithConfirm()
    }

    private func attemptCloseWithConfirm() {
        guard config.confirmBeforeClose else {
            dismissSelf(animated: true)
            return
        }
        let alert = UIAlertController(
            title: config.confirmCloseTitle.isEmpty ? L10n.confirmCloseTitle : config.confirmCloseTitle,
            message: config.confirmCloseMessage.isEmpty ? L10n.confirmCloseMessage : config.confirmCloseMessage,
            preferredStyle: .alert
        )
        alert.addAction(UIAlertAction(title: L10n.confirmStay, style: .cancel))
        alert.addAction(UIAlertAction(title: L10n.confirmLeave, style: .destructive) { [weak self] _ in
            self?.dismissSelf(animated: true)
        })
        present(alert, animated: true)
    }

    private func dismissSelf(animated: Bool) {
        if let nav = navigationController, nav.viewControllers.first !== self {
            nav.popViewController(animated: animated)
        } else {
            dismiss(animated: animated)
        }
    }

    private func handleEvent(_ event: SdkEvent) {
        // 容器内部观察:进度条已由 KVO 处理,此处保留扩展点
        _ = event
    }
}
