//
//  SettingsViewController.swift
//  VenusKitto
//
//  Created by Neoa on 2025/8/27.
//

import Foundation
import UIKit
import StoreKit
import AnyThinkBanner
import AnyThinkSDK
import AnyThinkInterstitial
import AnyThinkNative

// MARK: - Settings

final class SettingsViewController: UIViewController, ATAdLoadingDelegate, ATBannerDelegate, ATInterstitialDelegate, ATNativeADDelegate {

    // 背景图
    private let bgImageView: UIImageView = {
        let iv = UIImageView(image: UIImage(named: "wode465"))
        iv.contentMode = .scaleAspectFill
        iv.clipsToBounds = true
        return iv
    }()

    private let titleLabel: UILabel = {
        let l = UILabel()
        l.text = ""
        l.font = .systemFont(ofSize: 28, weight: .semibold)
        l.textColor = UIColor(hex: "#2B2B2B")
        return l
    }()

    // 顶部用户卡片（手绘边框）
    private let profileCard = UIImageView(image: UIImage(named: "wode402"))
    private let avatarView = UIImageView()
    private let phoneLabel = UILabel()
    private let idLabel = UILabel()
    private let profileChevron = UIImageView(image: UIImage(systemName: "chevron.right"))

    // 三个功能行
    private lazy var rateRow = makeRow(title: "给个好评", action: #selector(tapRate))
    private lazy var peteRow = makeRow(title: "我的宠物", action: #selector(tapPet))
    private lazy var feedbackRow = makeRow(title: "意见反馈", action: #selector(tapFeedback))
    private lazy var aboutRow = makeRow(title: "关于我们", action: #selector(tapAbout))
    
    // MARK: - 广告相关属性
    // 广告位ID
    private let interstitialPlacementID = "b68d88cc36bca8"
    private let bannerPlacementID = "b68d88cc2ab33d"
    private let nativeRenderPlacementID = "b68d88cc1605f1"
    
    // 横幅广告容器
    private let bannerContainer: UIView = {
        let v = UIView()
        v.backgroundColor = .clear
        v.translatesAutoresizingMaskIntoConstraints = false
        return v
    }()
    private var bannerHeightConstraint: NSLayoutConstraint?
    private var bannerView: ATBannerView?
    private var bannerSize: CGSize {
        let screenWidth = UIScreen.main.bounds.width
        let aspectRatio: CGFloat = 320 / 50
        let bannerWidth = screenWidth
        let bannerHeight = bannerWidth / aspectRatio
        return CGSize(width: bannerWidth, height: bannerHeight)
    }
    
    // 原生信息流广告容器
    private let nativeAdContainer: UIView = {
        let view = UIView()
        view.backgroundColor = .clear
        view.translatesAutoresizingMaskIntoConstraints = false
        view.isUserInteractionEnabled = true
        return view
    }()
    private var nativeAdView: ATNativeADView?
    private var selfRenderView: RenderUnitView?
    private var nativeAdOffer: ATNativeAdOffer?
    private var nativeAdHeightConstraint: NSLayoutConstraint?

    // 广告展示开始时间（毫秒），key 为 placementID
    private var adStartTimes: [String: Int64] = [:]
    
    // 当前时间戳（毫秒）
    private func nowMillis() -> Int64 {
        Int64(Date().timeIntervalSince1970 * 1000)
    }
    
    // 将毫秒时间戳格式化为 "yyyy-MM-dd HH:mm:ss"
    private func formatMillisToString(_ ms: Int64) -> String {
        let date = Date(timeIntervalSince1970: TimeInterval(ms) / 1000.0)
        let df = DateFormatter()
        df.locale = Locale(identifier: "en_US_POSIX")
        df.timeZone = TimeZone.current
        df.dateFormat = "yyyy-MM-dd HH:mm:ss"
        return df.string(from: date)
    }
    
    // ===== 当天广告观看次数（持久化到 UserDefaults）=====
    private func adCountKeyForToday() -> String {
        let df = DateFormatter()
        df.locale = Locale(identifier: "en_US_POSIX")
        df.dateFormat = "yyyy-MM-dd"
        return "adCount_" + df.string(from: Date())
    }

    private func incrementTodayAdCount() {
        let key = adCountKeyForToday()
        let current = UserDefaults.standard.integer(forKey: key)
        UserDefaults.standard.set(current + 1, forKey: key)
    }

    private func todayAdCount() -> Int {
        let key = adCountKeyForToday()
        return UserDefaults.standard.integer(forKey: key)
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = UIColor(hex: "#FFFEFC")
        setupBackground()
        
        if let backImage = UIImage(named: "AddPet385") {
            let backButton = UIBarButtonItem(image: backImage.withRenderingMode(.alwaysOriginal), style: .plain, target: self, action: #selector(tapCancel))
            navigationItem.leftBarButtonItem = backButton
        }

        NotificationCenter.default.addObserver(self,
                                               selector: #selector(handleAvatarUpdated(_:)),
                                               name: Notification.Name("UserAvatarUpdated"),
                                               object: nil)
        buildUI()
        fillUserInfo()
        
        // 加载广告
        loadBannerAd()
        loadNativeAd()
        
//        // 延迟加载插屏广告
//        DispatchQueue.main.asyncAfter(deadline: .now() + 3.0) {
//            self.loadInterstitialAd()
//        }
    }
    
    deinit {
        NotificationCenter.default.removeObserver(self, name: Notification.Name("UserAvatarUpdated"), object: nil)
    }
    
    @objc private func handleAvatarUpdated(_ note: Notification) {
        if let urlStr = note.object as? String, let url = URL(string: urlStr) {
            // 直接用通知携带的新 URL 刷新头像
            loadImage(from: url) { [weak self] img in
                self?.avatarView.image = img ?? UIImage(named: "Home372")
            }
            // 同步到本地，保证下次进入可以读到
            UserDefaults.standard.set(urlStr, forKey: "memberIcon")
        } else if let urlStr = (UserDefaults.standard.string(forKey: "memberIcon")),
                  let url = URL(string: urlStr) {
            // 兜底：没有携带 object 时，从本地读取刷新
            loadImage(from: url) { [weak self] img in
                self?.avatarView.image = img ?? UIImage(named: "Home372")
            }
        }
    }

    private func buildUI() {
        // 顶部标题
        view.addSubview(titleLabel)
        titleLabel.translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint.activate([
            titleLabel.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 12),
            titleLabel.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 24)
        ])

        // 用户卡片
        profileCard.contentMode = .scaleToFill
        profileCard.isUserInteractionEnabled = true
        let tapCard = UITapGestureRecognizer(target: self, action: #selector(tapProfile))
        profileCard.addGestureRecognizer(tapCard)
        view.addSubview(profileCard)
        profileCard.translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint.activate([
            profileCard.topAnchor.constraint(equalTo: titleLabel.bottomAnchor, constant: 12),
            profileCard.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 16),
            profileCard.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -16),
            profileCard.heightAnchor.constraint(equalToConstant: 92)
        ])

        avatarView.backgroundColor = UIColor(hex: "#FFF4CC")
        avatarView.layer.cornerRadius = 12
        avatarView.layer.masksToBounds = true
        avatarView.contentMode = .scaleAspectFill

        phoneLabel.font = .systemFont(ofSize: 16, weight: .semibold)
        phoneLabel.textColor = UIColor(hex: "#2B2B2B")

        idLabel.font = .systemFont(ofSize: 12)
        idLabel.textColor = UIColor(hex: "#9B9B9B")

        profileChevron.tintColor = UIColor(hex: "#5B4227")
        profileChevron.setContentCompressionResistancePriority(.required, for: .horizontal)

        [avatarView, phoneLabel, idLabel, profileChevron].forEach {
            $0.translatesAutoresizingMaskIntoConstraints = false
            profileCard.addSubview($0)
        }

        NSLayoutConstraint.activate([
            avatarView.leadingAnchor.constraint(equalTo: profileCard.leadingAnchor, constant: 16),
            avatarView.centerYAnchor.constraint(equalTo: profileCard.centerYAnchor),
            avatarView.widthAnchor.constraint(equalToConstant: 56),
            avatarView.heightAnchor.constraint(equalToConstant: 56),

            profileChevron.trailingAnchor.constraint(equalTo: profileCard.trailingAnchor, constant: -12),
            profileChevron.centerYAnchor.constraint(equalTo: profileCard.centerYAnchor),
            profileChevron.widthAnchor.constraint(equalToConstant: 16),
            profileChevron.heightAnchor.constraint(equalToConstant: 16),

            phoneLabel.leadingAnchor.constraint(equalTo: avatarView.trailingAnchor, constant: 12),
            phoneLabel.trailingAnchor.constraint(lessThanOrEqualTo: profileChevron.leadingAnchor, constant: -8),
            phoneLabel.bottomAnchor.constraint(equalTo: profileCard.centerYAnchor, constant: -2),

            idLabel.leadingAnchor.constraint(equalTo: phoneLabel.leadingAnchor),
            idLabel.topAnchor.constraint(equalTo: profileCard.centerYAnchor, constant: 2),
            idLabel.trailingAnchor.constraint(lessThanOrEqualTo: profileChevron.leadingAnchor, constant: -8)
        ])

        // 添加广告容器
        view.addSubview(bannerContainer)
        view.addSubview(nativeAdContainer)
        
        // 三个功能 row
        let stack = UIStackView(arrangedSubviews: [rateRow, peteRow, feedbackRow, aboutRow])
        stack.axis = .vertical
        stack.spacing = 12
        stack.alignment = .fill
        view.addSubview(stack)
        stack.translatesAutoresizingMaskIntoConstraints = false
        
        // 设置广告容器约束
        bannerHeightConstraint = bannerContainer.heightAnchor.constraint(equalToConstant: 0)
        bannerHeightConstraint?.isActive = true
        
        nativeAdHeightConstraint = nativeAdContainer.heightAnchor.constraint(equalToConstant: 0)
        nativeAdHeightConstraint?.isActive = true
        
        NSLayoutConstraint.activate([
            // 横幅广告容器（位于用户卡片下方）
            bannerContainer.topAnchor.constraint(equalTo: profileCard.bottomAnchor, constant: 8),
            bannerContainer.leadingAnchor.constraint(equalTo: view.leadingAnchor),
            bannerContainer.trailingAnchor.constraint(equalTo: view.trailingAnchor),
            
            // 功能按钮栈（位于横幅广告下方）
            stack.topAnchor.constraint(equalTo: bannerContainer.bottomAnchor, constant: 16),
            stack.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 16),
            stack.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -16),
            stack.bottomAnchor.constraint(lessThanOrEqualTo: nativeAdContainer.topAnchor, constant: -16),
            
            // 原生信息流广告容器（位于页面底部）
            nativeAdContainer.leadingAnchor.constraint(equalTo: view.leadingAnchor),
            nativeAdContainer.trailingAnchor.constraint(equalTo: view.trailingAnchor),
            nativeAdContainer.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor)
        ])
    }
    
    private func setupBackground() {
        view.insertSubview(bgImageView, at: 0)
        bgImageView.translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint.activate([
            bgImageView.topAnchor.constraint(equalTo: view.topAnchor),
            bgImageView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
            bgImageView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
            bgImageView.bottomAnchor.constraint(equalTo: view.bottomAnchor)
        ])
    }
    
    @objc private func tapCancel() { navigationController?.popViewController(animated: true)
    }


    private func makeRow(title: String, action: Selector) -> UIControl {
        let container = UIControl()
        container.backgroundColor = .white
        container.layer.cornerRadius = 14
        container.layer.shadowColor = UIColor.black.cgColor
        container.layer.shadowOpacity = 0.08
        container.layer.shadowRadius = 10
        container.layer.shadowOffset = CGSize(width: 0, height: 4)
        container.heightAnchor.constraint(equalToConstant: 64).isActive = true

        let label = UILabel()
        label.text = title
        label.font = .systemFont(ofSize: 16)
        label.textColor = UIColor(hex: "#2B2B2B")

        let chevron = UIImageView(image: UIImage(systemName: "chevron.right"))
        chevron.tintColor = UIColor(hex: "#5B4227")
        chevron.setContentCompressionResistancePriority(.required, for: .horizontal)

        container.addSubview(label)
        container.addSubview(chevron)
        label.translatesAutoresizingMaskIntoConstraints = false
        chevron.translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint.activate([
            label.leadingAnchor.constraint(equalTo: container.leadingAnchor, constant: 16),
            label.centerYAnchor.constraint(equalTo: container.centerYAnchor),

            chevron.trailingAnchor.constraint(equalTo: container.trailingAnchor, constant: -16),
            chevron.centerYAnchor.constraint(equalTo: container.centerYAnchor),
            chevron.widthAnchor.constraint(equalToConstant: 16),
            chevron.heightAnchor.constraint(equalToConstant: 16)
        ])

        container.addTarget(self, action: action, for: .touchUpInside)
        return container
    }

    private func fillUserInfo() {
        // 显示手机号（打码）与 ID
        let phone = UserDefaults.standard.string(forKey: "memberPhone") ?? "登录"
        let uid = UserDefaults.standard.string(forKey: "userId") ?? "--"
        phoneLabel.text = maskedPhone(phone)
        idLabel.text = "ID：\(uid)"

        if let urlStr = UserDefaults.standard.string(forKey: "memberIcon"),
           let url = URL(string: urlStr) {
            loadImage(from: url) { [weak self] img in
                self?.avatarView.image = img ?? UIImage(named: "Home372")
            }
        } else {
            avatarView.image = UIImage(named: "Home372")
        }
    }

    private func maskedPhone(_ s: String) -> String {
        let digits = s.filter { $0.isNumber }
        guard digits.count >= 7 else { return s }
        let start = digits.prefix(3)
        let end = digits.suffix(4)
        return "\(start)****\(end)"
    }

    private func loadImage(from url: URL, completion: @escaping (UIImage?) -> Void) {
        URLSession.shared.dataTask(with: url) { data, _, _ in
            guard let data = data, let img = UIImage(data: data) else {
                DispatchQueue.main.async { completion(nil) }
                return
            }
            DispatchQueue.main.async { completion(img) }
        }.resume()
    }

    // MARK: - Actions
    @objc private func tapProfile() {
        // 检查登录状态
        let isLoggedIn = UserDefaults.standard.bool(forKey: "isLogggedIn")
        let userToken = UserDefaults.standard.string(forKey: "userToken")
        
        // 如果没有登录状态或者没有有效的token，弹出登录界面
        if !isLoggedIn || userToken?.isEmpty != false {
            showLoginViewController()
            return
        }
        
        // 已登录，跳转到个人信息页
        let userSettingsVC = UserSettingsViewController()
        userSettingsVC.hidesBottomBarWhenPushed = true
        navigationController?.pushViewController(userSettingsVC, animated: true)
    }
    
    private func showLoginViewController() {
        let loginVC = LoginViewController()
        let navController = UINavigationController(rootViewController: loginVC)
        navController.modalPresentationStyle = .fullScreen
        present(navController, animated: true)
    }

    @objc private func tapRate() {
        // 跳 App Store 评分（占位）
        SKStoreReviewController.requestReview()

    }
    
    @objc private func tapPet() {
        
        // 检查登录状态
        let isLoggedIn = UserDefaults.standard.bool(forKey: "isLogggedIn")
        let userToken = UserDefaults.standard.string(forKey: "userToken")
        
        // 如果没有登录状态或者没有有效的token，弹出登录界面
        if !isLoggedIn || userToken?.isEmpty != false {
            showLoginViewController()
            return
        }

        //进入我的宠物界面
        let vc = MyPetsViewController()
        vc.hidesBottomBarWhenPushed = true
        navigationController?.pushViewController(vc, animated: true)
    }


    @objc private func tapFeedback() {
        let vc = FeedbackViewController()
        vc.hidesBottomBarWhenPushed = true
        navigationController?.pushViewController(vc, animated: true)
    }

    @objc private func tapAbout() {
        let vc = AboutViewController()
        vc.hidesBottomBarWhenPushed = true
        navigationController?.pushViewController(vc, animated: true)
    }
    
    // MARK: - 广告方法实现
    
    // MARK: - 横幅广告方法
    private func loadBannerAd() {
        var extra: [AnyHashable: Any] = [:]
        extra[kATAdLoadingExtraBannerAdSizeKey] = NSValue(cgSize: bannerSize)
        extra[kATAdLoadingExtraMediaExtraKey] = "SettingsVC"
        ATAdManager.shared().loadAD(withPlacementID: bannerPlacementID, extra: extra, delegate: self)
    }

    private func showBannerIfReady() {
        let config = ATShowConfig(scene: nil, showCustomExt: nil)
        guard let bView = ATAdManager.shared().retrieveBannerView(forPlacementID: bannerPlacementID, config: config) else { return }
        bView.delegate = self
        bView.presentingViewController = self
        bView.translatesAutoresizingMaskIntoConstraints = false
        bannerContainer.addSubview(bView)

        NSLayoutConstraint.activate([
            bView.centerXAnchor.constraint(equalTo: bannerContainer.centerXAnchor),
            bView.topAnchor.constraint(equalTo: bannerContainer.topAnchor),
            bView.widthAnchor.constraint(equalToConstant: bannerSize.width),
            bView.heightAnchor.constraint(equalToConstant: bannerSize.height)
        ])

        bannerView = bView
        bannerHeightConstraint?.constant = bannerSize.height
        UIView.animate(withDuration: 0.25) { self.view.layoutIfNeeded() }
    }

    private func removeBanner() {
        bannerView?.destroyBanner()
        bannerView?.removeFromSuperview()
        bannerView = nil
        bannerHeightConstraint?.constant = 0
        UIView.animate(withDuration: 0.25) { self.view.layoutIfNeeded() }
    }
    
    // MARK: - 插屏广告方法
    private func loadInterstitialAd() {
        let screenWidth = UIScreen.main.bounds.width
        let size = CGSize(width: screenWidth - 30.0, height: 300.0)
        let extra: [AnyHashable: Any] = [
            kATAdLoadingExtraMediaExtraKey: "SettingsView",
            kATInterstitialExtraAdSizeKey: NSValue(cgSize: size)
        ]
        ATAdManager.shared().loadAD(withPlacementID: interstitialPlacementID, extra: extra, delegate: self)
    }
    
    private func showInterstitialAd() {
        guard ATAdManager.shared().interstitialReady(forPlacementID: interstitialPlacementID) else {
            print("插屏广告尚未加载完成")
            return
        }
        ATAdManager.shared().showInterstitial(withPlacementID: interstitialPlacementID, in: self, delegate: self)
    }
    
    // MARK: - 原生信息流广告方法
    private func loadNativeAd() {
        let extra: [AnyHashable: Any] = [
            kATAdLoadingExtraMediaExtraKey: "SettingsVC",
            kATExtraInfoNativeAdSizeKey: NSValue(cgSize: CGSize(width: UIScreen.main.bounds.width - 24, height: 170))
        ]
        ATAdManager.shared().loadAD(withPlacementID: nativeRenderPlacementID, extra: extra, delegate: self)
    }

    private func showNativeAdIfReady() {
        // 检查广告是否准备好
        guard ATAdManager.shared().nativeAdReady(forPlacementID: nativeRenderPlacementID) else {
            print("Native ad not ready")
            return
        }
        
        // 获取广告offer
        guard let offer = ATAdManager.shared().getNativeAdOffer(withPlacementID: nativeRenderPlacementID) else {
            print("Failed to get native ad offer")
            return
        }
        
        self.nativeAdOffer = offer
        
        // 创建自渲染视图
        let selfRenderView = RenderUnitView(offer: offer)
        self.selfRenderView = selfRenderView
        
        // 初始化配置
        let config = ATNativeADConfiguration()
        config.adFrame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: 170)
        config.mediaViewFrame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: 150)
        config.delegate = self
        config.rootViewController = self
        config.sizeToFit = true
        config.videoPlayType = .alwaysAutoPlayType
        
        // 设置logo位置
        config.logoViewFrame = CGRect(x: UIScreen.main.bounds.width - 48, y: 140, width: 36, height: 20)
        
        // 创建原生广告视图
        let nativeAdView = ATNativeADView(configuration: config, currentOffer: offer, placementID: nativeRenderPlacementID)
        self.nativeAdView = nativeAdView
        
        // 获取mediaView
        if let mediaView = nativeAdView.getMediaView() {
            selfRenderView.installMediaView(mediaView)
        }
        
        // 创建可点击组件数组
        var clickableViewArray: [UIView] = []
        clickableViewArray.append(contentsOf: [
            selfRenderView.headlineLabel,
            selfRenderView.bodyLabel,
            selfRenderView.heroImageView
        ])
        
        // 注册点击事件
        nativeAdView.registerClickableViewArray(clickableViewArray)
        
        // 绑定组件
        let info = ATNativePrepareInfo.load { prepareInfo in
            prepareInfo.textLabel = selfRenderView.bodyLabel
            prepareInfo.titleLabel = selfRenderView.headlineLabel
            prepareInfo.mainImageView = selfRenderView.heroImageView
            prepareInfo.dislikeButton = selfRenderView.closeControl
            if let mv = selfRenderView.mediaContainer {
                prepareInfo.mediaView = mv
            }
        }
        nativeAdView.prepare(with: info)
        
        // 渲染广告
        offer.renderer(with: config, selfRenderView: selfRenderView, nativeADView: nativeAdView)
        
        // 添加到容器（必须把 nativeAdView 放到视图层级中，点击与视频追踪才会生效）
        nativeAdContainer.subviews.forEach { $0.removeFromSuperview() }
        nativeAdContainer.addSubview(nativeAdView)
        nativeAdView.translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint.activate([
            nativeAdView.leadingAnchor.constraint(equalTo: nativeAdContainer.leadingAnchor),
            nativeAdView.trailingAnchor.constraint(equalTo: nativeAdContainer.trailingAnchor),
            nativeAdView.topAnchor.constraint(equalTo: nativeAdContainer.topAnchor),
            nativeAdView.bottomAnchor.constraint(equalTo: nativeAdContainer.bottomAnchor)
        ])
        // 自渲染视图放入 nativeAdView 内
        nativeAdView.addSubview(selfRenderView)
        selfRenderView.translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint.activate([
            selfRenderView.leadingAnchor.constraint(equalTo: nativeAdView.leadingAnchor),
            selfRenderView.trailingAnchor.constraint(equalTo: nativeAdView.trailingAnchor),
            selfRenderView.topAnchor.constraint(equalTo: nativeAdView.topAnchor),
            selfRenderView.bottomAnchor.constraint(equalTo: nativeAdView.bottomAnchor)
        ])
        
        // 设置容器高度约束
        nativeAdHeightConstraint?.constant = 170
        UIView.animate(withDuration: 0.25) { self.view.layoutIfNeeded() }
        
        print("Native self-render ad displayed successfully")
    }
    
    private func removeNativeAd() {
        // 清理自渲染视图
        selfRenderView?.teardown()
        selfRenderView?.removeFromSuperview()
        selfRenderView = nil
        
        // 清理原生广告视图
        nativeAdView?.removeFromSuperview()
        nativeAdView?.destroyNative()
        nativeAdView = nil
        
        // 清理offer
        nativeAdOffer = nil
        
        nativeAdHeightConstraint?.constant = 0
        UIView.animate(withDuration: 0.25) { self.view.layoutIfNeeded() }
    }
    
    // MARK: - ATAdLoadingDelegate
    func didFinishLoadingAD(withPlacementID placementID: String) {
        if placementID == bannerPlacementID {
            if ATAdManager.shared().bannerAdReady(forPlacementID: placementID) {
                showBannerIfReady()
            }
            print("Banner Ad Loaded: \(placementID)")
        } else if placementID == interstitialPlacementID {
            if ATAdManager.shared().interstitialReady(forPlacementID: placementID) {
                showInterstitialAd()
            }
            print("Interstitial Ad Loaded: \(placementID)")
        } else if placementID == nativeRenderPlacementID {
            if ATAdManager.shared().nativeAdReady(forPlacementID: placementID) {
                showNativeAdIfReady()
            }
            print("Native Ad Loaded: \(placementID)")
        }
    }

    func didFailToLoadAD(withPlacementID placementID: String, error: Error) {
        print("Ad load failed(\(placementID)): \(error)")
    }

    func didRevenue(forPlacementID placementID: String, extra: [AnyHashable : Any]!) {
        print("Ad revenue: placement=\(placementID), extra=\(extra ?? [:])")
        uploadAdRevenue(placementID: placementID, extra: extra ?? [:])
    }

    // MARK: - ATBannerDelegate
    func bannerView(_ bannerView: ATBannerView, didTapCloseButtonWithPlacementID placementID: String, extra: [AnyHashable : Any]!) {
        removeBanner()
    }

    func bannerView(_ bannerView: ATBannerView, didShowAdWithPlacementID placementID: String, extra: [AnyHashable : Any]!) {
        print("Banner did show: \(placementID)")
        adStartTimes[placementID] = nowMillis()
        incrementTodayAdCount()
    }

    func bannerView(_ bannerView: ATBannerView, didClickWithPlacementID placementID: String, extra: [AnyHashable : Any]!) {
        print("Banner did click: \(placementID)")
    }

    func bannerView(_ bannerView: ATBannerView, didAutoRefreshWithPlacement placementID: String, extra: [AnyHashable : Any]!) {
        print("Banner auto refresh: \(placementID)")
    }

    func bannerView(_ bannerView: ATBannerView, failedToAutoRefreshWithPlacementID placementID: String, error: Error) {
        print("Banner auto refresh failed: \(placementID) error=\(error)")
    }

    func bannerView(_ bannerView: ATBannerView, didDeepLinkOrJumpForPlacementID placementID: String, extra: [AnyHashable : Any]!, result success: Bool) {
        print("Banner deeplink/jump: \(placementID) success=\(success)")
    }
    
    // MARK: - ATInterstitialDelegate
    func interstitialDidShow(forPlacementID placementID: String, extra: [AnyHashable : Any]) {
        print("插屏广告展示完成：\(placementID) \(extra)")
        adStartTimes[placementID] = nowMillis()
        incrementTodayAdCount()
    }
    
    func interstitialDidClick(forPlacementID placementID: String, extra: [AnyHashable : Any]) {
        print("插屏广告点击：\(placementID)")
    }
    
    func interstitialDidClose(forPlacementID placementID: String, extra: [AnyHashable : Any]) {
        print("插屏广告关闭：\(placementID) \(extra)")
    }
    
    // MARK: - ATNativeADDelegate
    func didShowNativeAd(in adView: ATNativeADView, placementID: String, extra: [AnyHashable: Any]?) {
        print("Native ad shown for \(placementID)")
        adStartTimes[placementID] = nowMillis()
        incrementTodayAdCount()
    }

    func didTapCloseButton(in adView: ATNativeADView, placementID: String, extra: [AnyHashable: Any]?) {
        print("Native ad closed for \(placementID)")
        removeNativeAd()
    }

    func didClickNativeAd(in adView: ATNativeADView, placementID: String, extra: [AnyHashable: Any]?) {
        print("Native ad clicked for \(placementID)")
    }
    
    // MARK: - 广告收益追踪
    private func uploadAdRevenue(placementID: String, extra: [AnyHashable: Any]) {
        // 计算 begin / finish（毫秒）并格式化为 "yyyy-MM-dd HH:mm:ss"
        let beginMs = adStartTimes[placementID] ?? nowMillis()
        let finishMs = nowMillis()
        print("testaa \(beginMs) \(String(describing: adStartTimes[placementID])) \(finishMs) \(placementID)")
        adStartTimes.removeValue(forKey: placementID) // 避免复用旧开始时间
        let beginTime = formatMillisToString(beginMs)
        let finishTime = formatMillisToString(finishMs)
        
        // 将 AnyHashable-key 的字典转为 String-key，且递归转为 JSON 可序列化类型
        func jsonSafe(_ value: Any) -> Any {
            if value is String || value is NSNumber || value is NSNull { return value }
            if let d = value as? [String: Any] { return d.mapValues { jsonSafe($0) } }
            if let d = value as? [AnyHashable: Any] {
                var nd: [String: Any] = [:]
                d.forEach { nd[String(describing: $0.key)] = jsonSafe($0.value) }
                return nd
            }
            if let arr = value as? [Any] { return arr.map { jsonSafe($0) } }

            if let v = value as? NSValue {
                // 处理常见 CoreGraphics 结构体；其余转描述串
                let type = String(cString: v.objCType)
                #if canImport(CoreGraphics)
                if type == "{CGSize=dd}" {
                    let s = v.cgSizeValue
                    return ["width": s.width, "height": s.height]
                } else if type == "{CGPoint=dd}" {
                    let p = v.cgPointValue
                    return ["x": p.x, "y": p.y]
                } else if type == "{CGRect={CGPoint=dd}{CGSize=dd}}" {
                    let r = v.cgRectValue
                    return ["x": r.origin.x, "y": r.origin.y, "width": r.size.width, "height": r.size.height]
                }
                #endif
                return v.description
            }

            if let date = value as? Date { return ISO8601DateFormatter().string(from: date) }
            if let url = value as? URL { return url.absoluteString }
            return String(describing: value)
        }

        // 注意：这里用 jsonSafe 处理每个值
        var extraDict: [String: Any] = [:]
        extra.forEach { (k, v) in
            extraDict[String(describing: k)] = jsonSafe(v)
        }

        // 便捷取值工具
        func str(_ key: String) -> String {
            if let v = extraDict[key] { return String(describing: v) }
            return ""
        }
        func intVal(_ key: String) -> Int {
            if let v = extraDict[key] as? Int { return v }
            if let s = extraDict[key] as? String, let i = Int(s) { return i }
            if let d = extraDict[key] as? Double { return Int(d) }
            return 0
        }
        func dbl(_ key: String) -> Double {
            if let v = extraDict[key] as? Double { return v }
            if let s = extraDict[key] as? String, let d = Double(s) { return d }
            if let i = extraDict[key] as? Int { return Double(i) }
            return 0
        }

        // —— 字段映射（对齐安卓） ——
        // adSourceId
        let adSourceId = intVal("adsource_id")
        // networkFormId / networkName / networkPlacementId
        let networkFormId = intVal("network_firm_id")
        let networkName = str("network_name")
        let networkPlacementId = str("network_placement_id")

        // placementId（iOS 回传里一般是 adunit_id；若无，用回调给的 placementID）
        let placementIdValue = str("adunit_id").isEmpty ? placementID : str("adunit_id")

        // recordId（有的 key 叫 requestId，也可能是 req_id，兜底）
        let recordId = str("requestId").isEmpty ? str("req_id") : str("requestId")

        // revenue（publisher_revenue）
        let revenue = dbl("publisher_revenue")

        // userId / nickName
//        let userId = UserDefaults.standard.string(forKey: "roleID") ?? ""
        let nickName = UserDefaults.standard.string(forKey: "memberName") ?? ""

        // ecpm：优先取 adsource_price；若没有，用 revenue*1000 估算一个（单位同 revenue）
        var ecpmStr = str("adsource_price")
        if ecpmStr.isEmpty {
            let ecpm = revenue * 1000.0
            ecpmStr = String(format: "%.6f", ecpm)
        }

        // adSourceIndex / adSourceType（优先 adsource_bid_type: 0=非竞价, 1=竞价）
        let adSourceIndex = intVal("adsource_index")
        // adSourceType 依据 adunit_format 映射：Native->0, RewardedVideo->1, Banner->2, Interstitial->3
        let adUnitFormatRaw = str("adunit_format")
        let adUnitFormat = adUnitFormatRaw.trimmingCharacters(in: .whitespacesAndNewlines).lowercased()
        let adSourceType: Int
        switch adUnitFormat {
        case "native":
            adSourceType = 0
        case "rewardedvideo", "rewarded_video", "rewarded":
            adSourceType = 1
        case "banner":
            adSourceType = 2
        case "interstitial":
            adSourceType = 3
        default:
            // 兜底逻辑：保持原有取值（若 SDK 提供 adsource_bid_type 则沿用）
            adSourceType = intVal("adsource_bid_type")
        }

        // resultJson：把 SDK 回传完整塞进去，便于排查
        let resultJsonData = try? JSONSerialization.data(withJSONObject: extraDict, options: [])
        let resultJson = resultJsonData.flatMap { String(data: $0, encoding: .utf8) } ?? "{}"
        
        // appId：iOS 若无可用 App ID，可用 Bundle Identifier 兜底
        let appId = kTakuAppID

        let adCount = todayAdCount()
        
        // 组装请求体（与安卓 map 字段完全一致）
        let body: [String: Any] = [
            "adSourceId": adSourceId,
            "beginTime": beginTime,
            "finishTime": finishTime,
            "networkFormId": networkFormId,
            "networkName": networkName,
            "networkPlacementId": networkPlacementId,
            "nickName": nickName,
            "placementId": placementIdValue,
            "recordId": recordId,
            "revenue": revenue,
            "userId": "",
            "ecpm": ecpmStr,
            "adSourceIndex": adSourceIndex,
            "adSourceType": adSourceType,
            "resultJson": resultJson,
            "appId": appId,
            "adCount": adCount,
            "iosId": UIDevice.current.identifierForVendor?.uuidString ?? "", //iOS 设备id
            "begintimestamp": beginMs,
            "finishtimestamp": finishMs
        ]
        // 发起上报
        let urlString = "\(baseURL)/ad/saveRecord"
        guard let url = URL(string: urlString) else {
            print("[AD-Upload] URL 无效: \(urlString)")
            return
        }

        var request = URLRequest(url: url)
        request.httpMethod = "POST"
        request.setValue("application/json", forHTTPHeaderField: "Content-Type")
        request.httpBody = try? JSONSerialization.data(withJSONObject: body, options: [])

        if let body = request.httpBody,
           let bodyString = String(data: body, encoding: .utf8) {
            print("[AD-Upload] Request URL: \(url)")
            print("[AD-Upload] Request Headers: \(request.allHTTPHeaderFields ?? [:])")
            print("[AD-Upload] Request Body: \(bodyString)")
        }

        
        URLSession.shared.dataTask(with: request) { data, response, error in
            if let error = error {
                print("[AD-Upload] 网络错误: \(error.localizedDescription)")
                return
            }
            if let http = response as? HTTPURLResponse {
                print("[AD-Upload] 响应状态码: \(http.statusCode)")
            }

            if let data = data, let s = String(data: data, encoding: .utf8) {
                print("[AD-Upload] 响应: \(s)")
            }
        }.resume()
    }
}

