//
//  PhotoBrowserController.swift

//
//  Created by Leon on 2025/7/26.
//

import Photos
import SnapKit
import UIKit
import Combine

enum PhotoBrowserType {
    /// 普通查看大图，无其他额外操作
    case normal
    /// 我的AI角色图片
    case roleMine
    /// 他人的AI角色图片
    case roleOthersInIm
    /// 浏览他人相册 &  Meet 查看大图
    case roleOthersInAlbum
    /// 聊天背景图选择(AI生图）
    case chatBackgroundGeneratedSelect
    /// 设置聊天背景图
    case chatBackgroundSet
}

class PhotoBrowserController: UIViewController, UIScrollViewDelegate, BrowseImageZoomViewDelegate {
    private let kScrollLeftAndRightSpace: CGFloat = 0
    @Published var currentIndex: Int = 0
    private var imageCount: Int = 0
    private var scrollView: UIScrollView!
    var titleView: NavigationView!
    private var titleTitleStackH: UIStackView!
    var titleLockIcon: EPIconTertiaryButton! // 🔒
    var titleunlockedIcon: EPIconPrimaryButton! // 🔓 + 主题背景色
    private var countLabel: UILabel?
    private var deleteButton: UIButton?

    // Data
    private var visibleZoomViews: Set<BrowseImageZoomView> = []
    private var reusableZoomViews: Set<BrowseImageZoomView> = []
    var imageModels: [PhotoBrowserModel] = []

    @Published var type: PhotoBrowserType = .normal
    private var cancellables = Set<AnyCancellable>()
    
    // Flag
    var isRequesting = false
    
    // MARK: - Commone通用业务Views
    var bottomGradientContainer: GradientView!
    var bottomGradientOperateStackV: UIStackView!
    
    // MARK: Role Mine
    /// 解锁方式：免费或coin解锁
    var rolePhotoUnlockEntry: RolePhotoUnlockEntryView!
    var setDefaultEntry: RolePhotoSetDefaultEntryView!
    var moreButton: EPIconGhostButton?
    
    // MARK:  Role See others

    var roleOthersContainer: SelectiveDeliveryEventsView?
    var roleOthersCenterLock: UIImageView?
    var iconLabel: CLIconLabel?
    var iconUnlockButton: StyleButton?
    
    // MARK:  通用的地步操作view
    /// 居中底部显示一个chipButton
    var bottomCommonOperateContainer: SelectiveDeliveryEventsView?
    var operateChipButton : EPChipContrastButton?
    var likeView: HeartLikeCountView?
    
    // MARK:  Chatbackground set
    var setBackgroundDisableButton: StyleButton!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .black
        setupScrollView()
        loadTitleView()
        
        // 其他业务通用的一些容器、View
        setupCommonContainers()
        setupOprateViews()
        
        setupEvent()
    }
    
    private func setupEvent(){
        $type.sink {[weak self] type in
            if type == .roleMine || type == .chatBackgroundSet{
                self?.moreButton?.isHidden = false
            }else{
                self?.moreButton?.isHidden = true
            }
        }.store(in: &cancellables)
        
        $currentIndex.sink {[weak self] index in
            self?.reloadStates(index: index)
        }.store(in: &cancellables)
        
        WalletCore.shared.$balance.sink {[weak self] balance in
            if let priceLabel = self?.iconLabel {
//                let balance = balance.balance ?? 0
//                let coin = Coin(cents: balance)
                priceLabel.contentLabel.text = balance.displayBalance()
            }
            
        }.store(in: &cancellables)
    }

    // MARK: - SetupViews
    private func setupScrollView() {
        scrollView = UIScrollView()
        scrollView.isHidden = true
        view.addSubview(scrollView)
        view.sendSubviewToBack(scrollView)

        scrollView.showsVerticalScrollIndicator = false
        scrollView.showsHorizontalScrollIndicator = false
        scrollView.contentInsetAdjustmentBehavior = .never
        scrollView.isPagingEnabled = true
        scrollView.bounces = true
        scrollView.backgroundColor = .clear
        scrollView.delegate = self

        scrollView.snp.makeConstraints { make in
            make.edges.equalTo(UIEdgeInsets(top: 0, left: -kScrollLeftAndRightSpace, bottom: 0, right: kScrollLeftAndRightSpace))
            make.width.equalTo(UIScreen.main.bounds.width + kScrollLeftAndRightSpace)
            make.height.equalTo(UIScreen.main.bounds.height)
        }
    }

    private func loadTitleView() {
        guard titleView == nil else {
            titleView?.alpha = 1
            return
        }

        titleView = NavigationView()
        titleView.bgView.alpha = 0
        titleView.setupBackButtonCloseIcon()
        titleView.clipsToBounds = false
        view.addSubview(titleView)
        titleView.snp.makeConstraints { make in
            make.top.leading.trailing.equalToSuperview()
            make.height.equalTo(UIWindow.statusBarHeight + 44)
        }
        let gradient = CLSystemToken.gradient(token: .cob)
        let gradientUnderTitle = GradientView(colors: [gradient.secondColor!, gradient.firstColor!], gradientType: .topToBottom) // [UIColor.c.cob.withAlphaComponent(0), UIColor.c.cbd]
        titleView.insertSubview(gradientUnderTitle, at: 0)
        gradientUnderTitle.snp.makeConstraints { make in
            make.leading.trailing.top.equalToSuperview()
            make.height.equalTo(140)
        }
        titleView.tapBackButtonAction = {[weak self] in
            self?.backButtonAction()
        }

        titleTitleStackH = {
            let v = UIStackView()
            v.spacing = 8
            v.alignment = .center
            titleView.addSubview(v)
            v.snp.makeConstraints { make in
                make.height.equalTo(44)
                make.centerX.equalToSuperview()
                make.bottom.equalToSuperview()
            }
            return v
        }()

        titleLockIcon = {
            // EPIconTertiaryButton
            let v = EPIconTertiaryButton(radius: .rectangle, iconSize: .small, iconCode: .iconPrivate)
            titleTitleStackH.addArrangedSubview(v)
            v.isHidden = true
            return v
        }()
        
        titleunlockedIcon = {
            let v = EPIconPrimaryButton(radius: .rectangle, iconSize: .small, iconCode: .iconPublic)
            titleTitleStackH.addArrangedSubview(v)
            v.isHidden = true
            return v
        }()

        countLabel = {
            let v = UILabel()
            titleTitleStackH.addArrangedSubview(v)
            v.textColor = .white
            v.font = .t.ttm
            v.textAlignment = .center
            return v
        }()
    }

    // MARK: - 各项业务对应的view
    private func setupCommonContainers(){
        bottomGradientContainer = {
            let gradient = CLSystemToken.gradient(token: .cob)
            let gradientUnderTitle = GradientView(colors: [gradient.firstColor!, gradient.secondColor!], gradientType: .topToBottom) // [UIColor.c.cob.withAlphaComponent(0), UIColor.c.cbd]
            view.addSubview(gradientUnderTitle)
            gradientUnderTitle.snp.makeConstraints { make in
                make.leading.trailing.bottom.equalToSuperview()
            }
            return gradientUnderTitle
        }()
        
        bottomGradientOperateStackV = {
            let v = UIStackView()
            v.axis = .vertical
            v.spacing = 16
            bottomGradientContainer!.addSubview(v)
            v.snp.makeConstraints { make in
                make.top.equalToSuperview().offset(48)
                make.leading.equalToSuperview().offset(24)
                make.trailing.equalToSuperview().offset(-24)
                make.bottom.equalToSuperview().offset(-16 - UIWindow.safeAreaBottom * 0.5)
            }
            return v
        }()
        
        bottomGradientContainer?.isHidden = true
    }
    
    private func setupOprateViews() {
        switch type {
        case .roleMine:
            createOperateViewOfRoleMine()
        case .roleOthersInIm, .roleOthersInAlbum:
            createOperateViewOfOthers()
            createBottomCommonOperateView()
        case .chatBackgroundSet:
            createChatBackgroundSetViews()
        case .chatBackgroundGeneratedSelect:
            createBottomCommonOperateView()
            setupChatBackgroundSelectView()
        default:
            break
        }
    }
    
    private func createBottomCommonOperateView(){
        bottomCommonOperateContainer = {
            let v = SelectiveDeliveryEventsView()
            view.insertSubview(v, belowSubview: titleView)
            v.snp.makeConstraints { make in
                make.edges.equalToSuperview()
            }
            return v
        }()
        
        operateChipButton = {
            let v = EPChipContrastButton()
            v.iconCode = .like
            v.addTarget(self, action: #selector(tapOperateChipButton(_:)), for: .touchUpInside)
            bottomCommonOperateContainer?.addSubview(v)
            v.snp.makeConstraints { make in
                make.centerX.equalToSuperview()
                make.bottom.equalToSuperview().offset(-16-UIWindow.safeAreaBottom*0.5)
            }
            v.isHidden = true
            return v
        }()
        
        likeView = {
            let v = HeartLikeCountView(viewSize: .xxl)
            bottomCommonOperateContainer?.addSubview(v)
            v.snp.makeConstraints { make in
                make.centerX.equalToSuperview()
                make.bottom.equalToSuperview().offset(-16-UIWindow.safeAreaBottom*0.5)
            }
            v.likeButton.addTarget(self, action: #selector(tapLikeButton), for: .touchUpInside)
            v.isHidden = true
            return v
        }()
        
        bottomCommonOperateContainer?.isHidden = true
        roleOthersContainer?.isHidden = true
    }
    

    private func setupChatBackgroundSelectView(){
        #warning("to do")
        //operateChipButton.text = "Select"
    }


    // MARK: - 看图控件
    func setupViews() {
        visibleZoomViews.forEach { view in
            view.prepareForReuse()
            view.removeFromSuperview()
            reusableZoomViews.insert(view)
        }
        visibleZoomViews.removeAll()

        imageCount = imageModels.count
        
        let width = UIScreen.main.bounds.width
        let height = UIScreen.main.bounds.height
        scrollView.contentOffset = CGPoint(x: (width + kScrollLeftAndRightSpace) * CGFloat(currentIndex), y: 0)
        scrollView.contentSize = CGSize(width: (width + kScrollLeftAndRightSpace) * CGFloat(imageCount), height: height)
        setupZoomView(at: currentIndex)
        reloadViews()
    }

    private func setupZoomView(at index: Int) {
        guard index < imageModels.count, index >= 0 else { return }
        let model = imageModels[index]
        let zoomView = BrowseImageZoomView(imageModel: model)
        zoomView.delegate = self
        let width = UIScreen.main.bounds.width
        let height = UIScreen.main.bounds.height
        zoomView.frame = CGRect(
            x: (width + kScrollLeftAndRightSpace) * CGFloat(index) + kScrollLeftAndRightSpace,
            y: 0,
            width: width,
            height: height
        )
        zoomView.displayIndex = index
        scrollView.addSubview(zoomView)
        visibleZoomViews.insert(zoomView)
    }

    private func reloadZoomView(_ zoomView: BrowseImageZoomView, at index: Int) {
        let width = UIScreen.main.bounds.width
        let height = UIScreen.main.bounds.height
        guard !imageModels.isEmpty else { return }
        let safeIndex = min(index, imageModels.count - 1)

        zoomView.frame = CGRect(
            x: (width + kScrollLeftAndRightSpace) * CGFloat(safeIndex) + kScrollLeftAndRightSpace,
            y: 0,
            width: width,
            height: height
        )
        zoomView.reloadImage(imageModels[safeIndex])
        zoomView.delegate = self
        zoomView.displayIndex = safeIndex
        scrollView.addSubview(zoomView)
        visibleZoomViews.insert(zoomView)
        reusableZoomViews.remove(zoomView)
    }

    // MARK: - Public
    func reloadViews() {
        guard imageCount > 1 else { return }

        var hasFrontDisplay = false
        var hasAfterDisplay = false

        visibleZoomViews.forEach { zoomView in
            if zoomView.displayIndex == currentIndex + 1 {
                hasAfterDisplay = true
            }
            if zoomView.displayIndex == currentIndex - 1 {
                hasFrontDisplay = true
            }
            if abs(zoomView.displayIndex - currentIndex) > 1 {
                zoomView.prepareForReuse()
                zoomView.removeFromSuperview()
                reusableZoomViews.insert(zoomView)
            }
        }

        visibleZoomViews.subtract(reusableZoomViews)

        if currentIndex + 1 < imageCount, !hasAfterDisplay {
            if let zoomView = reusableZoomViews.first {
                reloadZoomView(zoomView, at: currentIndex + 1)
            } else {
                setupZoomView(at: currentIndex + 1)
            }
        }

        if currentIndex - 1 >= 0, !hasFrontDisplay {
            if let zoomView = reusableZoomViews.first {
                reloadZoomView(zoomView, at: currentIndex - 1)
            } else {
                setupZoomView(at: currentIndex - 1)
            }
        }
    }
    
    func reloadCurrentZoomImage(){
        if let zoomView = visibleZoomViews.first {
            reloadZoomView(zoomView, at: currentIndex)
        }
    }

    @objc func backButtonAction() {
        let zoomView = visibleZoomViews.first { view in
            guard currentIndex < imageModels.count else { return false }
            return view.imageModel == imageModels[currentIndex]
        }

        if let zoomView = zoomView {
            zoomView.alpha = 0
            hideAnimation(with: zoomView.imageView, toRect: zoomView.imageModel?.sourceRect ?? .zero)
        } else {
            UIView.animate(withDuration: 0.3) { [weak self] in
                self?.setVCViewBackgroundColor(0)
            } completion: { _ in
                PhotoBrowserManager.shared.hidePhotoBrowser()
            }
        }
    }

    private func showAnimation(_ model: PhotoBrowserModel) {
        let imageView = UIImageView(frame: model.sourceRect)
        view.addSubview(imageView)

        imageView.contentMode = model.imageContentMode
        imageView.image = model.image ?? model.placeHolder
        imageView.backgroundColor = .black
        imageView.clipsToBounds = true
        if imageView.image == nil {
            imageView.isHidden = true
        }

        var imageWidth = imageView.image?.size.width ?? 1
        var imageHeight = imageView.image?.size.height ?? 1
        let scale = imageHeight / imageWidth
        if imageWidth < imageWidth && imageHeight >= UIScreen.main.bounds.height {
            imageHeight = UIScreen.main.bounds.height
            imageWidth = imageHeight / scale
        } else {
            imageWidth = UIScreen.main.bounds.width
            imageHeight = imageWidth * scale
        }

        let hasSourceRect = model.sourceRect.size.width > 0

        if hasSourceRect {
            UIView.animate(withDuration: 0.3) { [weak self] in
                guard let self = self else { return }
                imageView.backgroundColor = .black
                self.view.backgroundColor = .black
                imageView.center = CGPoint(x: UIScreen.main.bounds.width * 0.5, y: UIScreen.main.bounds.height * 0.5)
                imageView.bounds = CGRect(x: 0, y: 0, width: imageWidth, height: imageHeight)
            } completion: { [weak self] _ in
                guard let self = self else { return }
                self.scrollView.isHidden = false
                self.view.backgroundColor = .black
                imageView.removeFromSuperview()
                self.reloadCountLabel(hidden: self.type == .normal)
            }
        } else {
            imageView.backgroundColor = .black
            view.backgroundColor = .black
            imageView.center = CGPoint(x: UIScreen.main.bounds.width * 0.5, y: UIScreen.main.bounds.height * 0.5)
            imageView.bounds = CGRect(x: 0, y: 0, width: imageWidth, height: imageHeight)
            scrollView.isHidden = false
            view.backgroundColor = .black
            imageView.removeFromSuperview()
            reloadCountLabel(hidden: type == .normal)
        }
    }

    private func hideAnimation(with imageView: UIImageView, toRect rect: CGRect) {
        let newImageView = UIImageView(frame: PhotoBrowserModel.getViewRectForScreen(with: imageView))
        view.addSubview(newImageView)

        newImageView.contentMode = .scaleAspectFit
        newImageView.image = imageView.image
        newImageView.backgroundColor = .black
        newImageView.clipsToBounds = true

        UIView.animate(withDuration: 0.3) { [weak self] in
            self?.setVCViewBackgroundColor(0)
            newImageView.contentMode = .scaleAspectFill
            newImageView.backgroundColor = .black
            newImageView.frame = rect.size.width > 0 ? rect : newImageView.frame
            newImageView.alpha = rect.size.width > 0 ? 0.6 : 0
        } completion: { _ in
            PhotoBrowserManager.shared.hidePhotoBrowser()
            newImageView.removeFromSuperview()
        }
    }
    
    // MARK: - Helper
    /// ⚠️此方法好像有问题
    private func getCurrentZoomView() -> BrowseImageZoomView? {
        let zoomView = visibleZoomViews.first { view in
            guard currentIndex < imageModels.count else { return false }
            return view.imageModel == imageModels[currentIndex]
        }
        return zoomView
    }

    func getCurrentZoomView(byModel: PhotoBrowserModel) -> BrowseImageZoomView? {
        let zoomView = visibleZoomViews.first { view in
            guard currentIndex < imageModels.count else { return false }
            return view.imageModel == byModel
        }
        return zoomView
    }
    
    // MARK: - Functions

    func reloadCountLabel(hidden: Bool) {
        if hidden || imageCount <= 1 {
            countLabel?.alpha = 0
            return
        }

        countLabel?.alpha = 1
        countLabel?.text = "\(currentIndex + 1)/\(imageCount)"
        view.bringSubviewToFront(countLabel!)
    }
    
    func reloadStates(index: Int){
        guard imageModels.count > 0 else{
            return
        }
        let model = imageModels[index]
        //let album = model.aiAlbum
        reloadStatesByModel(model: model)
    }
    


    // MARK: - Public

    func setupView(with imageModels: [PhotoBrowserModel], currentIndex: Int) {
        guard !imageModels.isEmpty else { return }
        self.currentIndex = currentIndex
        imageCount = imageModels.count
        self.imageModels = imageModels
        showAnimation(imageModels[currentIndex])
        setupViews()
    }

    // MARK: - RoleBrowse about

    // MARK: - UIScrollViewDelegate

    func scrollViewDidScroll(_ scrollView: UIScrollView) {
        let index = Int(scrollView.contentOffset.x / (UIScreen.main.bounds.width + kScrollLeftAndRightSpace))
        // dlog("照片index: \(index)")
        guard index != currentIndex else { return }
        currentIndex = min(index, imageCount - 1)
        reloadViews()
        reloadCountLabel(hidden: false)
    }

    // MARK: - BrowseImageZoomViewDelegate

    func dismisAnimation(_ zoomImageView: UIImageView, toFrame frame: CGRect) {
        hideAnimation(with: zoomImageView, toRect: frame)
    }

    func setVCViewBackgroundColor(_ alpha: CGFloat) {
        view.backgroundColor = UIColor.black.withAlphaComponent(alpha)
        titleView?.alpha = alpha
        bottomGradientContainer?.alpha = alpha
        deleteButton?.alpha = alpha
        roleOthersContainer?.alpha = alpha
        bottomCommonOperateContainer?.alpha = alpha
    }

    func singleTapZoomView(_ zoomImageView: UIImageView) -> Bool {
        return true
    }

    @discardableResult
    func longPressZoomView(_ zoomView: BrowseImageZoomView) -> Bool {
        return true
    }

    deinit {
        print("♻️EGPhotoBrowserController dealloc")
    }
}
