import UIKit

fileprivate let nativeBaseViewControllerNibName = "NativeBaseViewController"

/// Base controller for native integration cases, provides title, body and sponsoredBy label, main and icon image views, callToAction button
/// For more details look at NativeBaseViewController xib
class NativeBaseViewController: UIViewController {
    
    /// Strong outlets: `InAppNativeViewController` detaches these views from the XIB stack to rebuild layouts;
    /// `weak` would release them after `removeFromSuperview()` and crash on next access.
    @IBOutlet var titleLabel: UILabel!
    @IBOutlet var iconView: UIImageView!
    @IBOutlet var mainImageView: UIImageView!
    @IBOutlet var bodyLabel: UILabel!
    @IBOutlet var callToActionButton: UIButton!
    @IBOutlet var sponsoredLabel: UILabel!
    
    /// When set, caps the computed main image height (e.g. compact native card layouts).
    var mainImageMaxHeight: CGFloat?
    
    /// When true, `updateMainImageViewHeightIfNeeded()` does nothing (e.g. fixed aspect-ratio container owns main image size).
    var skipMainImageDynamicHeight: Bool = false
    
    private var mainImageHeightConstraint: NSLayoutConstraint?
    
    convenience init() {
        self.init(nibName: nativeBaseViewControllerNibName, bundle: nil)
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        mainImageView.contentMode = .scaleAspectFit
        mainImageHeightConstraint = mainImageView.constraints.first { $0.firstAttribute == .height }
    }
    
    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        updateMainImageViewHeightIfNeeded()
    }
    
    /// 在把模版嵌进列表 cell、或异步写入 `mainImageView.image` 之后调用，避免首帧 `bounds` 仍为 0 时高度约束未更新导致裁切。
    func invalidateNativeMainImageLayoutIfNeeded() {
        updateMainImageViewHeightIfNeeded()
    }
    
    /// 根据 mainImageView 中的图片宽高比更新高度约束，使主图按比例自适应展示
    private func updateMainImageViewHeightIfNeeded() {
        if skipMainImageDynamicHeight {
            return
        }
        guard let image = mainImageView.image,
              let heightConstraint = mainImageHeightConstraint,
              image.size.width > 0 else { return }
        let availableWidth = mainImageView.bounds.width > 1
            ? mainImageView.bounds.width
            : max(view.bounds.width - 30, 1)
        let aspectRatio = image.size.height / image.size.width
        var newHeight = availableWidth * aspectRatio
        if let cap = mainImageMaxHeight {
            newHeight = min(newHeight, cap)
        }
        if abs(heightConstraint.constant - newHeight) > 1 {
            heightConstraint.constant = newHeight
            view.setNeedsLayout()
        }
    }
    
    /// Toggle the XIB height constraint on `mainImageView` (e.g. off when embedding in a fixed aspect-ratio container).
    func setMainImageHeightConstraintActive(_ active: Bool) {
        mainImageHeightConstraint?.isActive = active
    }
    
    /// Rebind main image height after programmatic layout rebuild (e.g. In-App Native feed card).
    func bindMainImageHeightConstraint(_ constraint: NSLayoutConstraint) {
        mainImageHeightConstraint?.isActive = false
        mainImageHeightConstraint = constraint
    }
    
    func updateCallToActionButtonTitle(_ title: String?) {
        let displayTitle = NativeFeedLayout.displayCallToAction(title)
        guard var config = callToActionButton.configuration else {
            callToActionButton.setTitle(displayTitle, for: .normal)
            return
        }
        config.title = displayTitle
        callToActionButton.configuration = config
    }
    
    func applyFeedNativeLayout() {
        skipMainImageDynamicHeight = true
        NativeFeedLayout.apply(
            container: view,
            iconView: iconView,
            titleLabel: titleLabel,
            bodyLabel: bodyLabel,
            sponsoredLabel: sponsoredLabel,
            mainImageView: mainImageView,
            callToActionButton: callToActionButton,
            onMainImageHeightConstraint: { [weak self] constraint in
                self?.bindMainImageHeightConstraint(constraint)
            }
        )
    }
}

enum NativeFeedLayout {
    static func displayCallToAction(_ callToAction: String?) -> String {
        let trimmed = callToAction?.trimmingCharacters(in: .whitespacesAndNewlines) ?? ""
        if trimmed.isEmpty {
            return "下载"
        }

        switch trimmed.lowercased() {
        case "install", "download", "get", "get it", "get the app":
            return "下载"
        default:
            return trimmed
        }
    }

    static func apply(
        container: UIView,
        iconView: UIImageView,
        titleLabel: UILabel,
        bodyLabel: UILabel,
        sponsoredLabel: UILabel,
        mainImageView: UIView,
        callToActionButton: UIButton,
        onMainImageHeightConstraint: ((NSLayoutConstraint) -> Void)? = nil,
        edgeInsets: UIEdgeInsets = UIEdgeInsets(top: 15, left: 15, bottom: 0, right: 15),
        useSafeArea: Bool = true
    ) {
        func clearConstraints(on view: UIView) {
            view.removeConstraints(view.constraints)
        }

        if let containerStack = container.subviews.first(where: { $0 is UIStackView }) {
            [iconView, titleLabel, bodyLabel, mainImageView, callToActionButton, sponsoredLabel].forEach {
                $0.removeFromSuperview()
            }
            containerStack.removeFromSuperview()
        } else {
            container.subviews.filter {
                $0 !== iconView &&
                $0 !== titleLabel &&
                $0 !== bodyLabel &&
                $0 !== mainImageView &&
                $0 !== callToActionButton &&
                $0 !== sponsoredLabel
            }.forEach { $0.removeFromSuperview() }
        }

        let cardView = UIView()
        cardView.translatesAutoresizingMaskIntoConstraints = false
        cardView.backgroundColor = UIColor(white: 0.95, alpha: 1)
        cardView.layer.cornerRadius = 4
        container.addSubview(cardView)

        iconView.translatesAutoresizingMaskIntoConstraints = false
        iconView.contentMode = .scaleAspectFill
        iconView.clipsToBounds = true
        iconView.layer.cornerRadius = 8

        titleLabel.translatesAutoresizingMaskIntoConstraints = false
        titleLabel.font = .boldSystemFont(ofSize: 16)
        titleLabel.numberOfLines = 2

        bodyLabel.translatesAutoresizingMaskIntoConstraints = false
        bodyLabel.font = .systemFont(ofSize: 13)
        bodyLabel.textColor = .secondaryLabel
        bodyLabel.numberOfLines = 2

        sponsoredLabel.translatesAutoresizingMaskIntoConstraints = false
        sponsoredLabel.font = .systemFont(ofSize: 12)
        sponsoredLabel.textColor = .secondaryLabel
        sponsoredLabel.numberOfLines = 1

        mainImageView.translatesAutoresizingMaskIntoConstraints = false
        if let imageView = mainImageView as? UIImageView {
            imageView.contentMode = .scaleAspectFill
            imageView.clipsToBounds = true
        }

        callToActionButton.translatesAutoresizingMaskIntoConstraints = false
        callToActionButton.setContentHuggingPriority(.required, for: .vertical)
        callToActionButton.setContentCompressionResistancePriority(.required, for: .vertical)
        var buttonConfig = UIButton.Configuration.filled()
        buttonConfig.baseBackgroundColor = .systemBlue
        buttonConfig.baseForegroundColor = .white
        buttonConfig.cornerStyle = .medium
        buttonConfig.contentInsets = NSDirectionalEdgeInsets(top: 12, leading: 16, bottom: 12, trailing: 16)
        callToActionButton.configuration = buttonConfig

        [iconView, titleLabel, bodyLabel, sponsoredLabel, mainImageView, callToActionButton].forEach {
            clearConstraints(on: $0)
            cardView.addSubview($0)
        }

        let mainImageHeight = mainImageView.heightAnchor.constraint(equalToConstant: 180)
        mainImageHeight.isActive = true
        onMainImageHeightConstraint?(mainImageHeight)

        let topAnchor = useSafeArea ? container.safeAreaLayoutGuide.topAnchor : container.topAnchor
        let leadingAnchor = useSafeArea ? container.safeAreaLayoutGuide.leadingAnchor : container.leadingAnchor
        let trailingAnchor = useSafeArea ? container.safeAreaLayoutGuide.trailingAnchor : container.trailingAnchor

        var constraints: [NSLayoutConstraint] = [
            cardView.topAnchor.constraint(equalTo: topAnchor, constant: edgeInsets.top),
            cardView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: edgeInsets.left),
            cardView.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -edgeInsets.right),

            iconView.topAnchor.constraint(equalTo: cardView.topAnchor, constant: 12),
            iconView.leadingAnchor.constraint(equalTo: cardView.leadingAnchor, constant: 12),
            iconView.widthAnchor.constraint(equalToConstant: 48),
            iconView.heightAnchor.constraint(equalToConstant: 48),

            titleLabel.topAnchor.constraint(equalTo: iconView.topAnchor),
            titleLabel.leadingAnchor.constraint(equalTo: iconView.trailingAnchor, constant: 12),
            titleLabel.trailingAnchor.constraint(equalTo: cardView.trailingAnchor, constant: -12),

            bodyLabel.topAnchor.constraint(equalTo: titleLabel.bottomAnchor, constant: 4),
            bodyLabel.leadingAnchor.constraint(equalTo: titleLabel.leadingAnchor),
            bodyLabel.trailingAnchor.constraint(equalTo: titleLabel.trailingAnchor),

            sponsoredLabel.topAnchor.constraint(equalTo: bodyLabel.bottomAnchor, constant: 4),
            sponsoredLabel.leadingAnchor.constraint(equalTo: titleLabel.leadingAnchor),
            sponsoredLabel.trailingAnchor.constraint(equalTo: titleLabel.trailingAnchor),
            sponsoredLabel.bottomAnchor.constraint(greaterThanOrEqualTo: iconView.bottomAnchor),

            mainImageView.topAnchor.constraint(equalTo: sponsoredLabel.bottomAnchor, constant: 12),
            mainImageView.leadingAnchor.constraint(equalTo: cardView.leadingAnchor),
            mainImageView.trailingAnchor.constraint(equalTo: cardView.trailingAnchor),

            callToActionButton.topAnchor.constraint(equalTo: mainImageView.bottomAnchor, constant: 12),
            callToActionButton.leadingAnchor.constraint(equalTo: cardView.leadingAnchor, constant: 12),
            callToActionButton.trailingAnchor.constraint(equalTo: cardView.trailingAnchor, constant: -12),
            callToActionButton.heightAnchor.constraint(equalToConstant: 48),
            callToActionButton.bottomAnchor.constraint(equalTo: cardView.bottomAnchor, constant: -12)
        ]

        if !useSafeArea {
            constraints.append(container.bottomAnchor.constraint(equalTo: cardView.bottomAnchor, constant: edgeInsets.bottom))
        }

        NSLayoutConstraint.activate(constraints)
    }
}
