import UIKit
import TencentQianWebView

/// DemoSwift 主页 —— 纯 Swift 消费 OC 版 `TencentQianWebView` framework。
///
/// 与 `ios-swift/Demo`(消费 Swift SDK)的差异:此处调用的 OC SDK 使用 `TQ` 前缀,
/// 通过 framework module 直接 `import`(SDK 是 `DEFINES_MODULE:YES` 的 framework,
/// 无需 bridging header)。每个调用点的 OC→Swift 桥接写法见各方法注释。
///
/// - URL 输入框:粘贴客户后端发起的真实 flowId URL
/// - 三按钮:① 容器 ② 配置 ③ 自检
/// - 日志 TextView:实时打印最近一次 SignResult / SdkEvent
final class DemoViewController: UIViewController {

    private let urlField = UITextField()
    private let logView = UITextView()
    private let prewarmBizTypeField = UITextField()
    private var bizTypeOptions: [String] = ["single-sign", "batch-sign", "enterprise-register", "join-enterprise"]

    override func viewDidLoad() {
        super.viewDidLoad()
        title = "Tencent Qian H5 Demo (Swift→OC SDK)"
        view.backgroundColor = DemoCompat.background

        let hint = UILabel()
        hint.text = "粘贴客户后端发起的 flowId URL,演示三种集成方式:"
        hint.numberOfLines = 0
        hint.font = .systemFont(ofSize: 13)
        hint.textColor = DemoCompat.secondaryLabel

        urlField.placeholder = "https://quick.qian.tencent.cn/sign/...?flowId=..."
        urlField.borderStyle = .roundedRect
        urlField.font = .systemFont(ofSize: 14)
        urlField.autocapitalizationType = .none
        urlField.autocorrectionType = .no
        urlField.returnKeyType = .done
        urlField.delegate = self

        let btn1 = makeButton(title: "① 容器模式打开签署页", action: #selector(onContainer))
        let btn2 = makeButton(title: "② 配置模式改造既有 WebView", action: #selector(onConfigurator))
        let btn3 = makeButton(title: "③ 打开自检页(beta)", action: #selector(onCompatibility))

        // ── 预热档位（真机验证）：bizType 输入 + 一行三档，颜色由浅到深表达「预热深度递增」 ──
        let prewarmLabel = UILabel()
        prewarmLabel.text = "预热bizType:"
        prewarmLabel.font = .systemFont(ofSize: 13)
        prewarmLabel.textColor = DemoCompat.secondaryLabel
        prewarmLabel.setContentHuggingPriority(.required, for: .horizontal)

        prewarmBizTypeField.text = "single-sign"
        prewarmBizTypeField.borderStyle = .roundedRect
        prewarmBizTypeField.font = .systemFont(ofSize: 13)
        prewarmBizTypeField.autocapitalizationType = .none
        prewarmBizTypeField.autocorrectionType = .no
        prewarmBizTypeField.setContentHuggingPriority(.defaultLow, for: .horizontal)
        prewarmBizTypeField.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)

        let bizTypePickerBtn = UIButton(type: .system)
        bizTypePickerBtn.setTitle("▼", for: .normal)
        bizTypePickerBtn.titleLabel?.font = .systemFont(ofSize: 14)
        bizTypePickerBtn.setContentHuggingPriority(.required, for: .horizontal)
        bizTypePickerBtn.setContentCompressionResistancePriority(.required, for: .horizontal)
        bizTypePickerBtn.addTarget(self, action: #selector(onShowBizTypePicker), for: .touchUpInside)

        let prewarmRow = UIStackView(arrangedSubviews: [prewarmLabel, prewarmBizTypeField, bizTypePickerBtn])
        prewarmRow.axis = .horizontal
        prewarmRow.spacing = 8
        prewarmRow.alignment = .center

        let btnMinimal = makePrewarmButton(title: "迷你·DNS", color: UIColor(red: 0x8C/255, green: 0x8C/255, blue: 0x8C/255, alpha: 1), action: #selector(onPrewarmMinimal))
        let btnLight = makePrewarmButton(title: "LIGHT·内核", color: UIColor(red: 0x52/255, green: 0xC4/255, blue: 0x1A/255, alpha: 1), action: #selector(onPrewarmLight))
        let btnHeavy = makePrewarmButton(title: "HEAVY·池", color: UIColor(red: 0x23/255, green: 0x78/255, blue: 0x04/255, alpha: 1), action: #selector(onPrewarmHeavy))
        let prewarmButtons = UIStackView(arrangedSubviews: [btnMinimal, btnLight, btnHeavy])
        prewarmButtons.axis = .horizontal
        prewarmButtons.spacing = 8
        prewarmButtons.distribution = .fillEqually

        let btnRelease = makePrewarmButton(title: "释放预热池（签署完成后主动释放）", color: UIColor(red: 0xFF/255, green: 0x4D/255, blue: 0x4F/255, alpha: 1), action: #selector(onReleasePool))

        logView.font = DemoCompat.monoFont
        logView.isEditable = false
        logView.backgroundColor = DemoCompat.secondaryBackground
        logView.layer.cornerRadius = 6
        logView.textContainerInset = UIEdgeInsets(top: 8, left: 8, bottom: 8, right: 8)

        let logTitle = UILabel()
        logTitle.text = "SDK 回调日志"
        logTitle.font = .boldSystemFont(ofSize: 14)
        let clearBtn = UIButton(type: .system)
        clearBtn.setTitle("清空", for: .normal)
        clearBtn.addTarget(self, action: #selector(onClear), for: .touchUpInside)
        let logHeader = UIStackView(arrangedSubviews: [logTitle, UIView(), clearBtn])
        logHeader.axis = .horizontal
        logHeader.alignment = .center

        let stack = UIStackView(arrangedSubviews: [
            prewarmRow, prewarmButtons, btnRelease, hint, urlField, btn1, btn2, btn3, logHeader, logView
        ])
        stack.axis = .vertical
        stack.spacing = 8
        stack.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(stack)

        NSLayoutConstraint.activate([
            stack.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 16),
            stack.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 16),
            stack.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -16),
            stack.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -16)
        ])

        // 配置预热（UA 与 buildConfig 对齐，池实例才能复用）
        let prewarmCfg = TQPrewarmConfig.default()
        prewarmCfg.environment = .beta
        prewarmCfg.preferredLanguage = "zh-CN"
        prewarmCfg.userAgentExtra = "qianwv-demo-swift/1.0.0"
        TQWebViewPrewarmer.configure(prewarmCfg)

        TQWebViewPrewarmer.getMenuBizTypes { [weak self] bizTypes in
            DispatchQueue.main.async {
                self?.bizTypeOptions = bizTypes
            }
        }
    }

    private func makeButton(title: String, action: Selector) -> UIButton {
        let btn = UIButton(type: .system)
        btn.setTitle(title, for: .normal)
        btn.titleLabel?.font = .systemFont(ofSize: 15, weight: .medium)
        btn.backgroundColor = .systemBlue
        btn.setTitleColor(.white, for: .normal)
        btn.layer.cornerRadius = 8
        btn.contentEdgeInsets = UIEdgeInsets(top: 12, left: 12, bottom: 12, right: 12)
        btn.addTarget(self, action: action, for: .touchUpInside)
        return btn
    }

    // MARK: - 三按钮

    /// 容器模式。
    /// OC: `+openFromPresenter:url:config:callbacks:animated:completion:`
    /// Swift 桥接(实测):`open(fromPresenter:url:config:callbacks:animated:completion:)`
    @objc private func onContainer() {
        guard let url = currentUrl() else { return }
        // OC: `+defaultConfig` → Swift(实测): `default()`
        let cfg = TQWebViewConfig.default()
        cfg.topBarTitle = "电子签署(容器模式)"
        cfg.userAgentExtra = "qianwv-demo-swift/1.0.0"
        cfg.confirmBeforeClose = true
        TQWebView.open(fromPresenter: self,
                       url: url,
                       config: cfg,
                       callbacks: makeCallbacks(),
                       animated: true,
                       completion: nil)
    }

    @objc private func onConfigurator() {
        guard let url = currentUrl() else { return }
        let vc = ConfiguratorDemoViewController(url: url, callbacks: makeCallbacks())
        present(UINavigationController(rootViewController: vc), animated: true)
    }

    /// 自检页。
    /// OC: `+openCompatibilityTestFromPresenter:customUrl:config:callbacks:animated:`
    /// Swift 桥接(实测):`openCompatibilityTest(fromPresenter:customUrl:config:callbacks:animated:)`
    @objc private func onCompatibility() {
        TQWebView.openCompatibilityTest(fromPresenter: self,
                                        customUrl: nil,
                                        config: nil,
                                        callbacks: makeCallbacks(),
                                        animated: true)
    }

    @objc private func onClear() {
        logView.text = ""
    }

    @objc private func onShowBizTypePicker() {
        let alert = UIAlertController(title: "选择 bizType", message: nil, preferredStyle: .actionSheet)
        for biz in bizTypeOptions {
            alert.addAction(UIAlertAction(title: biz, style: .default) { [weak self] _ in
                self?.prewarmBizTypeField.text = biz
            })
        }
        alert.addAction(UIAlertAction(title: "取消", style: .cancel))
        present(alert, animated: true)
    }

    // MARK: - 预热（真机验证）

    /// 预热触发。
    /// OC: `+prewarm:bizType:` → Swift 桥接: `prewarm(_:bizType:)`
    /// MINIMAL 档无需 bizType(传 nil);LIGHT/HEAVY 档必填。
    private func triggerPrewarm(_ level: TQPrewarmLevel) {
        let raw = (prewarmBizTypeField.text ?? "").trimmingCharacters(in: .whitespacesAndNewlines)
        let bizType = raw.isEmpty ? "single-sign" : raw
        switch level {
        case .minimal:
            TQWebViewPrewarmer.prewarm(.minimal, bizType: nil)
            appendLog("[prewarm] MINIMAL (DNS) triggered")
        case .light:
            TQWebViewPrewarmer.prewarm(.light, bizType: bizType)
            appendLog("[prewarm] LIGHT (kernel init) bizType=\(bizType) triggered")
        case .heavy:
            TQWebViewPrewarmer.prewarm(.heavy, bizType: bizType)
            appendLog("[prewarm] HEAVY (off-screen pool) bizType=\(bizType) triggered")
        }
        showToast("已触发预热")
    }

    @objc private func onPrewarmMinimal() { triggerPrewarm(.minimal) }
    @objc private func onPrewarmLight() { triggerPrewarm(.light) }
    @objc private func onPrewarmHeavy() { triggerPrewarm(.heavy) }

    /// 释放预热池。
    /// OC: `+releaseAll` → Swift 桥接: `releaseAll()`
    @objc private func onReleasePool() {
        TQWebViewPrewarmer.releaseAll()
        appendLog("[prewarm] pool released (releaseAll)")
        showToast("已释放预热池")
    }

    /// 【接入方示范】业务入口页销毁 == 业务流程结束 → 释放预热池。
    ///
    /// 建议在承载签署流程的业务入口页/会话终点（如本 VC 的 deinit）调用 releaseAll：
    /// 它会销毁预热 WKWebView 实例 并重置去重状态，使预热系统回到初始态——
    /// 这样用户下次再进入同一业务流程时，prewarm 能重新生效。
    /// 若只想临时回收内存、仍保留“本会话已预热过”的去重记账，则改用 release。
    deinit {
        TQWebViewPrewarmer.releaseAll()
    }

    private func makePrewarmButton(title: String, color: UIColor, action: Selector) -> UIButton {
        let btn = UIButton(type: .system)
        btn.setTitle(title, for: .normal)
        btn.titleLabel?.font = .systemFont(ofSize: 14)
        btn.backgroundColor = color
        btn.setTitleColor(.white, for: .normal)
        btn.layer.cornerRadius = 6
        btn.contentEdgeInsets = UIEdgeInsets(top: 10, left: 8, bottom: 10, right: 8)
        btn.addTarget(self, action: action, for: .touchUpInside)
        return btn
    }

    // MARK: - 工具

    private func currentUrl() -> String? {
        let s = (urlField.text ?? "").trimmingCharacters(in: .whitespacesAndNewlines)
        if s.isEmpty {
            let alert = UIAlertController(title: nil, message: "请先粘贴 flowId URL", preferredStyle: .alert)
            alert.addAction(UIAlertAction(title: "确定", style: .default))
            present(alert, animated: true)
            return nil
        }
        return s
    }

    /// 回调构造。
    /// OC: `+callbacksWithOnSignResult:onEvent:` → Swift 桥接(实测):`init(onSignResult:onEvent:)`
    /// 备选(若 init 导入名不同):`TQSignCallbacks()` 后赋值 `.onSignResult` / `.onEvent` 属性。
    private func makeCallbacks() -> TQSignCallbacks {
        return TQSignCallbacks(
            onSignResult: { [weak self] result in
                self?.appendLog("⮞ SignResult action=\(result.action) result=\(result.result) flowId=\(result.flowId) extras=\(result.extras)")

                // OC SDK 的 action/result 是 NSString *const 常量,Swift 里为 String,用 == 比较。
                // (Swift SDK 则是可穷举 enum;OC SDK 不变,此处接受字符串比较形态。)
                let human: String
                if result.action == TQSignActionSign             { human = "签署" }
                else if result.action == TQSignActionFill        { human = "填写" }
                else if result.action == TQSignActionRejectSign  { human = "拒签" }
                else if result.action == TQSignActionRejectFill  { human = "拒填" }
                else if result.action == TQSignActionView        { human = "查看" }
                else if result.action.isEmpty                    { human = "无 action" }
                else                                              { human = "未知 action(\(result.action))" }
                let ok = result.result == TQSignResultStatusSuccess
                let alert = UIAlertController(
                    title: nil,
                    message: "\(human) \(ok ? "成功" : "未成功")",
                    preferredStyle: .alert
                )
                alert.addAction(UIAlertAction(title: "确定", style: .default))
                self?.present(alert, animated: true)
            },
            onEvent: { [weak self] event in
                self?.appendLog("• \(event)")

                // OC SDK 事件用 marker protocol + 具体事件类,Swift 用 `is` 判断分发。
                DispatchQueue.main.async {
                    guard let self = self else { return }
                    if event is TQWebContentProcessTerminatedEvent {
                        self.showToast("页面异常,正在恢复…")
                    }
                }
            }
        )
    }

    private func appendLog(_ line: String) {
        DispatchQueue.main.async { [weak self] in
            guard let self = self else { return }
            self.logView.text.append(line + "\n")
            let bottom = NSRange(location: self.logView.text.count - 1, length: 1)
            self.logView.scrollRangeToVisible(bottom)
        }
    }

    /// 简易 Toast 演示(iOS 无原生 Toast,用临时 UILabel 模拟)
    private func showToast(_ message: String) {
        let label = UILabel()
        label.text = message
        label.textAlignment = .center
        label.font = .systemFont(ofSize: 14)
        label.textColor = .white
        label.backgroundColor = UIColor.black.withAlphaComponent(0.75)
        label.layer.cornerRadius = 8
        label.clipsToBounds = true
        label.numberOfLines = 0
        label.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(label)
        NSLayoutConstraint.activate([
            label.centerXAnchor.constraint(equalTo: view.centerXAnchor),
            label.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -60),
            label.widthAnchor.constraint(lessThanOrEqualTo: view.widthAnchor, constant: -40),
            label.heightAnchor.constraint(greaterThanOrEqualToConstant: 36)
        ])
        label.layoutMargins = UIEdgeInsets(top: 8, left: 16, bottom: 8, right: 16)

        UIView.animate(withDuration: 0.3, delay: 2.0, options: .curveEaseOut) {
            label.alpha = 0
        } completion: { _ in
            label.removeFromSuperview()
        }
    }
}

extension DemoViewController: UITextFieldDelegate {
    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        textField.resignFirstResponder()
        return true
    }
}
