import UIKit
import GoogleMobileAds

// MARK: - SettingsViewController

final class SettingsViewController: UIViewController {

    // MARK: - Callbacks

    var onLanguageTapped: (() -> Void)?
    var onNotificationsTapped: (() -> Void)?
    var onHelpCenterTapped: (() -> Void)?
    var onAboutTapped: (() -> Void)?
    var onShowCardNumberChanged: ((Bool) -> Void)?

    // MARK: - State

    private var showCardNumber: Bool = {
        // First launch: key doesn't exist → default ON and persist it
        if UserDefaults.standard.object(forKey: "masked") == nil {
            UserDefaults.standard.set(true, forKey: "masked")
            return true
        }
        return UserDefaults.standard.bool(forKey: "masked")
    }() {
        didSet { onShowCardNumberChanged?(showCardNumber) }
    }

    // MARK: - UI

    private let scrollView   = UIScrollView()
    private let contentView  = UIView()

    // Ad banner
    private let adContainer  = UIView()
    private var bannerView   = GADBannerView()
    private var bannerRetryWorkItem: DispatchWorkItem?
    private var isBannerAdLoaded = false
    private var isBannerLoadInFlight = false
    private let bannerRetryDelay: TimeInterval = 20

    // Dynamic constraints — toggled on ad load/fail
    private var generalTopNoAd:   NSLayoutConstraint!
    private var generalTopWithAd: NSLayoutConstraint!

    // Stored anchors for chaining
    private var headerBottomAnchor: NSLayoutYAxisAnchor!
    private var lastBottomAnchor:   NSLayoutYAxisAnchor!

    // TODO: Replace with real ad unit ID before release
    private let adUnitID = "ca-app-pub-3389368171983845/7916200416"

    // MARK: - Lifecycle

    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = Theme.Color.background
        setupScrollView()
        setupHeader()
        setupAdBanner()
        setupGeneralSection()
        setupAppSection()
        setupFooter()
    }

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        loadBannerAdIfNeeded(reason: "viewDidAppear")
    }

    deinit {
        bannerRetryWorkItem?.cancel()
    }

    // MARK: - ScrollView

    private func setupScrollView() {
        scrollView.showsVerticalScrollIndicator = false
        scrollView.translatesAutoresizingMaskIntoConstraints = false
        contentView.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(scrollView)
        scrollView.addSubview(contentView)

        NSLayoutConstraint.activate([
            scrollView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
            scrollView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
            scrollView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
            scrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor),

            contentView.topAnchor.constraint(equalTo: scrollView.topAnchor),
            contentView.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor),
            contentView.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor),
            contentView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor),
            contentView.widthAnchor.constraint(equalTo: scrollView.widthAnchor)
        ])
    }

    // MARK: - Header (no search button)

    private func setupHeader() {
        let titleLabel = UILabel()
        titleLabel.text = L10n.settingsTitle
        titleLabel.font = Theme.Font.title(weight: .bold)
        titleLabel.textColor = Theme.Color.textPrimary
        titleLabel.translatesAutoresizingMaskIntoConstraints = false
        contentView.addSubview(titleLabel)

        NSLayoutConstraint.activate([
            titleLabel.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 20),
            titleLabel.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 24)
        ])

        headerBottomAnchor = titleLabel.bottomAnchor
        lastBottomAnchor   = titleLabel.bottomAnchor
    }

    // MARK: - Ad Banner

    private func setupAdBanner() {
        let adSize = GADCurrentOrientationAnchoredAdaptiveBannerAdSizeWithWidth(
            UIScreen.main.bounds.width - 48
        )
        bannerView = GADBannerView(adSize: adSize)
        bannerView.adUnitID = adUnitID
        bannerView.rootViewController = self
        bannerView.delegate = self
        bannerView.translatesAutoresizingMaskIntoConstraints = false

        adContainer.backgroundColor = .clear
        adContainer.clipsToBounds   = true
        adContainer.isHidden        = true
        adContainer.translatesAutoresizingMaskIntoConstraints = false
        adContainer.addSubview(bannerView)
        contentView.addSubview(adContainer)

        NSLayoutConstraint.activate([
            adContainer.topAnchor.constraint(equalTo: headerBottomAnchor, constant: 16),
            adContainer.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 24),
            adContainer.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -24),

            bannerView.topAnchor.constraint(equalTo: adContainer.topAnchor),
            bannerView.leadingAnchor.constraint(equalTo: adContainer.leadingAnchor),
            bannerView.trailingAnchor.constraint(equalTo: adContainer.trailingAnchor),
            bannerView.bottomAnchor.constraint(equalTo: adContainer.bottomAnchor),
            bannerView.heightAnchor.constraint(equalToConstant: CGFloat(adSize.size.height))
        ])

        lastBottomAnchor = adContainer.bottomAnchor
    }

    private func loadBannerAdIfNeeded(reason: String) {
        guard !isBannerAdLoaded, !isBannerLoadInFlight else { return }
        guard isViewLoaded, view.window != nil else {
            logAdMob("skip load: view is not visible", reason: reason)
            return
        }

        bannerRetryWorkItem?.cancel()
        bannerView.rootViewController = self
        isBannerLoadInFlight = true
        logAdMob("loading banner", reason: reason)
        bannerView.load(GADRequest())
    }

    private func scheduleBannerRetry(after delay: TimeInterval = 20) {
        bannerRetryWorkItem?.cancel()

        let workItem = DispatchWorkItem { [weak self] in
            self?.loadBannerAdIfNeeded(reason: "retry")
        }
        bannerRetryWorkItem = workItem

        logAdMob("scheduling retry in \(Int(delay))s")
        DispatchQueue.main.asyncAfter(deadline: .now() + delay, execute: workItem)
    }

    private func logAdMob(_ message: String, reason: String? = nil, error: Error? = nil) {
        var parts = ["[AdMob][Settings]", message]
        if let reason {
            parts.append("reason=\(reason)")
        }
        parts.append("adUnitID=\(bannerView.adUnitID ?? "-")")
        parts.append("visible=\(viewIfLoaded?.window != nil)")
        parts.append("loaded=\(isBannerAdLoaded)")
        parts.append("inFlight=\(isBannerLoadInFlight)")
        parts.append("rootVC=\(String(describing: type(of: bannerView.rootViewController)))")

        if let nsError = error as NSError? {
            parts.append("errorDomain=\(nsError.domain)")
            parts.append("errorCode=\(nsError.code)")
            parts.append("error=\(nsError.localizedDescription)")
        }

        debugLog(parts.joined(separator: " | "))
    }

    // MARK: - General Section

    private func setupGeneralSection() {
        let sectionLabel = makeSectionLabel(L10n.sectionGeneral)
        contentView.addSubview(sectionLabel)

        // Two top constraints — only one active at a time
        generalTopNoAd   = sectionLabel.topAnchor.constraint(equalTo: headerBottomAnchor, constant: 28)
        generalTopWithAd = sectionLabel.topAnchor.constraint(equalTo: adContainer.bottomAnchor, constant: 20)
        generalTopNoAd.isActive = true   // default: no ad

        NSLayoutConstraint.activate([
            sectionLabel.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 24)
        ])

        let card = makeCard()
        contentView.addSubview(card)
        NSLayoutConstraint.activate([
            card.topAnchor.constraint(equalTo: sectionLabel.bottomAnchor, constant: 10),
            card.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 24),
            card.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -24)
        ])

        let languageRow = SettingsRow(
            icon: "globe", title: L10n.languageTitle,
            detail: L10n.languageValue, accessory: .chevron
        )
        languageRow.onTap = { [weak self] in self?.onLanguageTapped?() }

        let toggleRow = SettingsRow(
            icon: "eye", title: L10n.showCardNumberTitle,
            subtitle: L10n.showCardNumberDesc, accessory: .toggle(isOn: showCardNumber)
        )
        toggleRow.onToggleChanged = { [weak self] isOn in self?.showCardNumber = isOn }

        let stack = UIStackView(arrangedSubviews: [languageRow, makeSeparator(), toggleRow])
        stack.axis = .vertical
        stack.translatesAutoresizingMaskIntoConstraints = false
        card.addSubview(stack)
        NSLayoutConstraint.activate([
            stack.topAnchor.constraint(equalTo: card.topAnchor, constant: 4),
            stack.leadingAnchor.constraint(equalTo: card.leadingAnchor),
            stack.trailingAnchor.constraint(equalTo: card.trailingAnchor),
            stack.bottomAnchor.constraint(equalTo: card.bottomAnchor, constant: -4)
        ])

        lastBottomAnchor = card.bottomAnchor
    }

    // MARK: - App Section

    private func setupAppSection() {
        let sectionLabel = makeSectionLabel(L10n.sectionApp)
        contentView.addSubview(sectionLabel)
        NSLayoutConstraint.activate([
            sectionLabel.topAnchor.constraint(equalTo: lastBottomAnchor, constant: 24),
            sectionLabel.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 24)
        ])

        let card = makeCard()
        contentView.addSubview(card)
        NSLayoutConstraint.activate([
            card.topAnchor.constraint(equalTo: sectionLabel.bottomAnchor, constant: 10),
            card.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 24),
            card.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -24)
        ])

        let helpRow = SettingsRow(
            icon: "questionmark.circle", title: L10n.helpCenterTitle,
            subtitle: L10n.helpCenterDesc, accessory: .chevron
        )
        helpRow.onTap = { [weak self] in self?.onHelpCenterTapped?() }

        let appVersion = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String ?? ""
        let buildNumber = Bundle.main.infoDictionary?["CFBundleVersion"] as? String ?? ""
        let versionSubtitle = "\(L10n.aboutAppDesc) \(appVersion) (Build \(buildNumber))"
        let aboutRow = SettingsRow(
            icon: "info.circle", title: L10n.aboutAppTitle,
            subtitle: versionSubtitle, accessory: .chevron
        )
        aboutRow.onTap = { [weak self] in self?.onAboutTapped?() }

        let stack = UIStackView(arrangedSubviews: [helpRow, makeSeparator(), aboutRow])
        stack.axis = .vertical
        stack.translatesAutoresizingMaskIntoConstraints = false
        card.addSubview(stack)
        NSLayoutConstraint.activate([
            stack.topAnchor.constraint(equalTo: card.topAnchor, constant: 4),
            stack.leadingAnchor.constraint(equalTo: card.leadingAnchor),
            stack.trailingAnchor.constraint(equalTo: card.trailingAnchor),
            stack.bottomAnchor.constraint(equalTo: card.bottomAnchor, constant: -4)
        ])

        lastBottomAnchor = card.bottomAnchor
    }

    // MARK: - Footer

    private func setupFooter() {
        let appLabel = UILabel()
        appLabel.text = L10n.footerCopyright
        appLabel.font = Theme.Font.caption(weight: .semibold)
        appLabel.textColor = Theme.Color.textSecondary
        appLabel.textAlignment = .center

        let stack = UIStackView(arrangedSubviews: [appLabel])
        stack.axis      = .vertical
        stack.spacing   = 4
        stack.alignment = .center
        stack.translatesAutoresizingMaskIntoConstraints = false
        contentView.addSubview(stack)

        NSLayoutConstraint.activate([
            stack.topAnchor.constraint(equalTo: lastBottomAnchor, constant: 32),
            stack.centerXAnchor.constraint(equalTo: contentView.centerXAnchor),
            stack.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -140)
        ])
    }

    // MARK: - Helpers

    private func makeSectionLabel(_ text: String) -> UILabel {
        let label = UILabel()
        label.text = text
        label.font = Theme.Font.caption(weight: .semibold)
        label.textColor = Theme.Color.textSecondary
        label.translatesAutoresizingMaskIntoConstraints = false
        return label
    }

    private func makeCard() -> UIView {
        let card = UIView()
        card.backgroundColor = Theme.Color.card
        card.layer.cornerRadius = 16
        card.layer.shadowColor   = UIColor.black.cgColor
        card.layer.shadowOpacity = 0.06
        card.layer.shadowOffset  = CGSize(width: 0, height: 2)
        card.layer.shadowRadius  = 8
        card.translatesAutoresizingMaskIntoConstraints = false
        return card
    }

    private func makeSeparator() -> UIView {
        let line = UIView()
        line.backgroundColor = Theme.Color.background
        line.translatesAutoresizingMaskIntoConstraints = false
        line.heightAnchor.constraint(equalToConstant: 1).isActive = true
        return line
    }
}

// MARK: - GADBannerViewDelegate

extension SettingsViewController: GADBannerViewDelegate {
    func bannerViewDidReceiveAd(_ bannerView: GADBannerView) {
        bannerRetryWorkItem?.cancel()
        isBannerLoadInFlight = false
        isBannerAdLoaded = true
        logAdMob("banner loaded")
        generalTopNoAd.isActive   = false
        generalTopWithAd.isActive = true
        UIView.animate(withDuration: 0.3) {
            self.adContainer.isHidden = false
            self.view.layoutIfNeeded()
        }
    }

    func bannerView(_ bannerView: GADBannerView, didFailToReceiveAdWithError error: Error) {
        isBannerLoadInFlight = false
        isBannerAdLoaded = false
        logAdMob("banner failed", error: error)
        generalTopWithAd.isActive = false
        generalTopNoAd.isActive   = true
        UIView.animate(withDuration: 0.3) {
            self.adContainer.isHidden = true
            self.view.layoutIfNeeded()
        }
        scheduleBannerRetry(after: bannerRetryDelay)
    }
}

// MARK: - SettingsRow

private enum SettingsAccessory {
    case chevron
    case toggle(isOn: Bool)
    case detail(String)
}

private final class SettingsRow: UIView {

    var onTap: (() -> Void)?
    var onToggleChanged: ((Bool) -> Void)?

    init(icon: String,
         title: String,
         subtitle: String? = nil,
         detail: String? = nil,
         accessory: SettingsAccessory) {
        super.init(frame: .zero)

        // Icon — grey background, green icon (same as HistoryView)
        let iconContainer = UIView()
        iconContainer.backgroundColor = Theme.Color.background
        iconContainer.layer.cornerRadius = 10

        let config = UIImage.SymbolConfiguration(pointSize: 15, weight: .medium)
        let iconView = UIImageView(image: UIImage(systemName: icon, withConfiguration: config))
        iconView.tintColor = Theme.Color.secondary
        iconView.contentMode = .scaleAspectFit
        iconView.translatesAutoresizingMaskIntoConstraints = false
        iconContainer.addSubview(iconView)

        // Labels
        let titleLabel = UILabel()
        titleLabel.text = title
        titleLabel.font = Theme.Font.body(weight: .medium)
        titleLabel.textColor = Theme.Color.textPrimary
        titleLabel.numberOfLines = 0

        let subtitleLabel = UILabel()
        subtitleLabel.text = subtitle
        subtitleLabel.font = Theme.Font.caption(weight: .regular)
        subtitleLabel.textColor = Theme.Color.textSecondary
        subtitleLabel.isHidden = subtitle == nil
        subtitleLabel.numberOfLines = 0

        // Right accessory
        let rightView: UIView
        switch accessory {
        case .chevron:
            let chevronConfig = UIImage.SymbolConfiguration(pointSize: 13, weight: .semibold)
            let img = UIImageView(image: UIImage(systemName: "chevron.right", withConfiguration: chevronConfig))
            img.tintColor = Theme.Color.textSecondary
            img.contentMode = .scaleAspectFit
            rightView = img
        case .toggle(let isOn):
            let sw = UISwitch()
            sw.isOn = isOn
            sw.onTintColor = Theme.Color.primary
            sw.addTarget(self, action: #selector(toggleChanged(_:)), for: .valueChanged)
            rightView = sw
        case .detail(let text):
            let lbl = UILabel()
            lbl.text = text
            lbl.font = Theme.Font.body(weight: .regular)
            lbl.textColor = Theme.Color.textSecondary
            rightView = lbl
        }

        let labelStack = UIStackView(arrangedSubviews: [titleLabel, subtitleLabel])
        labelStack.axis    = .vertical
        labelStack.spacing = 2

        let hStack = UIStackView(arrangedSubviews: [iconContainer, labelStack, rightView])
        hStack.axis      = .horizontal
        hStack.spacing   = 14
        hStack.alignment = .center
        hStack.translatesAutoresizingMaskIntoConstraints = false
        addSubview(hStack)

        NSLayoutConstraint.activate([
            iconContainer.widthAnchor.constraint(equalToConstant: 36),
            iconContainer.heightAnchor.constraint(equalToConstant: 36),
            iconView.centerXAnchor.constraint(equalTo: iconContainer.centerXAnchor),
            iconView.centerYAnchor.constraint(equalTo: iconContainer.centerYAnchor),
            iconView.widthAnchor.constraint(equalToConstant: 18),
            iconView.heightAnchor.constraint(equalToConstant: 18),

            hStack.topAnchor.constraint(equalTo: topAnchor, constant: 14),
            hStack.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 16),
            hStack.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -16),
            hStack.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -14)
        ])

        // labelStack selalu menyusut agar rightView tidak terdorong keluar
        labelStack.setContentHuggingPriority(.defaultLow, for: .horizontal)
        labelStack.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
        rightView.setContentHuggingPriority(.required, for: .horizontal)
        rightView.setContentCompressionResistancePriority(.required, for: .horizontal)

        if case .chevron = accessory {
            let tap = UITapGestureRecognizer(target: self, action: #selector(rowTapped))
            addGestureRecognizer(tap)
            isUserInteractionEnabled = true
        }

        if let detail = detail, case .chevron = accessory {
            let detailLabel = UILabel()
            detailLabel.text = detail
            detailLabel.font = Theme.Font.body(weight: .regular)
            detailLabel.textColor = Theme.Color.textSecondary
            detailLabel.setContentHuggingPriority(.required, for: .horizontal)
            detailLabel.setContentCompressionResistancePriority(.required, for: .horizontal)

            hStack.removeArrangedSubview(rightView)
            rightView.removeFromSuperview()
            hStack.addArrangedSubview(detailLabel)

            let chevronConfig = UIImage.SymbolConfiguration(pointSize: 13, weight: .semibold)
            let img = UIImageView(image: UIImage(systemName: "chevron.right", withConfiguration: chevronConfig))
            img.tintColor = Theme.Color.textSecondary
            img.contentMode = .scaleAspectFit
            hStack.addArrangedSubview(img)
        }
    }

    required init?(coder: NSCoder) { nil }

    @objc private func rowTapped() { onTap?() }
    @objc private func toggleChanged(_ sender: UISwitch) { onToggleChanged?(sender.isOn) }
}
