//
//  CommonUploadImageButton.swift

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

import UIKit
import SnapKit

enum CommentUploadState: Int {
    case loading
    case success
    case failed
    case checkdFailed
}

class CommonUploadImageButton: UIButton {
    private var indicatorBGView: UIView!
    private var indicatorView: UIActivityIndicatorView!
    private var retryButton: UIButton!
    private var errorButton: UIButton!
    private var contentImageView: UIImageView!
    private var closeButton: EPIconTertiaryDarkButton!
    
    @Published private(set) var uploadState: CommentUploadState = .loading {
        didSet {
            reloadViews()
        }
    }
    private(set) var imageUrlNowIfHave: String?
    var uploadModel: CommentImageModel?
    
    var optionErrorMsg: String?
    var closeAction: ((CommonUploadImageButton) -> Void)?
    var tapRetryAction: ((CommonUploadImageButton) -> Void)?
    
    var uploadSuceess: ((CommonUploadImageButton) -> Void)?
    var uploadOrCheckFailed: ((CommonUploadImageButton) -> Void)?
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        initializeViews()
    }
    
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        initializeViews()
    }
    
    private func initializeViews() {
        layer.cornerRadius = 8.0
        layer.masksToBounds = true
        
        contentImageView = {
            let imageView = UIImageView()
            addSubview(imageView)
            imageView.contentMode = .scaleAspectFill
            imageView.snp.makeConstraints { make in
                make.edges.equalToSuperview()
            }
            return imageView
        }()
        
        indicatorBGView = {
            let view = UIView()
            addSubview(view)
            view.isHidden = true
            view.layer.borderColor = UIColor.c.civn.cgColor//EPSystemToken.color(.important_variant_normal).cgColor
            view.layer.cornerRadius = layer.cornerRadius
            view.backgroundColor = UIColor.c.csedn//EPSystemToken.color(.surface_element_dark_normal)
            view.snp.makeConstraints { make in
                make.edges.equalToSuperview()
            }
            return view
        }()
        
        indicatorView = {
            let indicator = UIActivityIndicatorView()
            addSubview(indicator)
            indicator.color = .c.ctpsn//EPSystemToken.color(.txt_primary_specialmap_normal)
            indicator.isHidden = true
            indicator.snp.makeConstraints { make in
                make.center.equalToSuperview()
                make.size.equalTo(CGSize(width: 24, height: 24))
            }
            return indicator
        }()
        
        closeButton = {
            let button = EPIconTertiaryDarkButton(radius: .round, iconSize: .xxs, iconCode: .delete)
            addSubview(button)
            button.isHidden = true
            button.touchAreaInsets = UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10)
            button.addTarget(self, action: #selector(closeButtonAction), for: .touchUpInside)
            button.snp.makeConstraints { make in
                make.trailing.equalToSuperview().offset(-8)
                make.top.equalToSuperview().offset(8)
                make.size.equalTo(CGSize(width: 16, height: 16))
            }
            return button
        }()
        
        retryButton = {
            let button = UIButton(type: .custom)
            addSubview(button)
            button.isHidden = true
            let image = MWIconFont.image(fromIcon: .iconReload, size: .init(width: 16, height: 16), color: .c.ctpsn)
            button.setImage(image, for: .normal)
            button.contentMode = .center
            button.touchAreaInsets = UIEdgeInsets(top: 2, left: 2, bottom: 2, right: 2)
            button.addTarget(self, action: #selector(retryButtonAction), for: .touchUpInside)
            button.snp.makeConstraints { make in
                make.center.equalToSuperview()
                make.size.equalTo(CGSize(width: 32, height: 32))
            }
            return button
        }()
        
        errorButton = {
            let button = UIButton(type: .custom)
            addSubview(button)
            button.isHidden = true
            button.setImage(UIImage(named: "album_reupload"), for: .normal)
            button.touchAreaInsets = UIEdgeInsets(top: 2, left: 2, bottom: 2, right: 2)
            button.addTarget(self, action: #selector(errorButtonAction), for: .touchUpInside)
            button.snp.makeConstraints { make in
                make.center.equalToSuperview()
                make.size.equalTo(CGSize(width: 32, height: 32))
            }
            return button
        }()
        
        setupImageDefaultState()
    }
    
    private func reloadViews() {
        indicatorBGView.isHidden = true
        indicatorBGView.layer.borderWidth = 0
        if indicatorView.isAnimating {
            indicatorView.stopAnimating()
        }
        retryButton.isHidden = true
        closeButton.isHidden = true
        errorButton.isHidden = true
        
        switch uploadState {
        case .loading:
            indicatorBGView.isHidden = false
            indicatorView.startAnimating()
        case .failed:
            indicatorBGView.isHidden = false
            retryButton.isHidden = false
            closeButton.isHidden = false
            indicatorBGView.layer.borderWidth = CLSystemToken.border(token: .bs)//EPSystemToken.border(.s)
        case .success:
            closeButton.isHidden = false
        case .checkdFailed:
            indicatorBGView.isHidden = false
            closeButton.isHidden = false
            errorButton.isHidden = false
            indicatorBGView.layer.borderWidth = CLSystemToken.border(token: .bs)//EPSystemToken.border(.s)
        }
        
        if imageView?.image != nil {
            setImage(nil, for: .normal)
        }
    }
    
    // MARK: - Public Methods
    
    func setupImageDefaultState() {
        
        let image = MWIconFont.image(fromIcon: .iconUploadimg, size: .init(width: 24, height: 24), color: .c.cttn)
        setImage(image, for: .normal)
        backgroundColor = .c.csen//EPSystemToken.color(.surface_element_normal)
        
        contentImageView.image = nil
        imageUrlNowIfHave = nil
        closeButton.isHidden = true
        indicatorBGView.isHidden = true
        errorButton.isHidden = true
    }
    
    @discardableResult
    func bindViewImage(_ image: UIImage, report: Bool = false, checkImage: Bool = false) -> UploadPhotoM {
        contentImageView.image = image
        uploadState = .loading
        DispatchQueue.main.async {[weak self] in
            // UploadPhotoM is returned finally
            self?.uploadState = .loading
        }
        
        let model = CommentImageModel()
        model.isReport = report
        uploadModel = model
        let photo = model.startUpload(with: image, checkImage: checkImage)
        uploadModel?.imageUploadComplete = { [weak self] result, photo in
            guard let self = self else { return }
            if result {
                self.uploadState = .success
                self.uploadSuceess?(self)
            } else if photo.imageChecked && photo.imageCheckIsViolation {
                self.uploadState = .checkdFailed
                self.uploadOrCheckFailed?(self)
            } else {
                self.uploadState = .failed
                self.uploadOrCheckFailed?(self)
            }
            self.reloadViews()
        }
        reloadViews()
        return photo
    }
    
    func bindViewImageNoUpload(_ image: UIImage) {
        contentImageView.image = image
        uploadState = .loading
        reloadViews()
    }
    
    func bindViewImage(_ image: UIImage?) {
        guard let img = image else{
            return
        }
        contentImageView.image = img
    }
    
    func bindSuccessImage(_ image: UIImage?) {
        guard let img = image else{
            return
        }
        contentImageView.image = img
        uploadState = .success
    }
    
    func bindViewImageUrl(_ imageUrl: String) {
        imageUrlNowIfHave = imageUrl
        //contentImageView.sd_setImage(with: URL(string: imageUrl), placeholderImage: UIImage.imgPlaceHolder)
        contentImageView.loadImage(imageUrl)
        let model = CommentImageModel()
        model.uploadUrl = imageUrl
        uploadModel = model
        uploadState = .success
        reloadViews()
    }
    
    func givtStateOutsize(_ state: CommentUploadState) {
        uploadState = state
    }
    
    func setupCornerRadius(_ radius: CGFloat) {
        layer.cornerRadius = radius
        indicatorBGView.layer.cornerRadius = radius
    }
    
    // MARK: - Actions
    
    @objc private func retryButtonAction() {
        uploadState = .loading
        reloadViews()
        if let tapRetryAction = tapRetryAction {
            tapRetryAction(self)
        } else {
            if let img = uploadModel?.image{
                uploadModel?.startUpload(with: img)
            }else{
                fatalError()
            }
        }
    }
    
    @objc private func errorButtonAction() {
        if let optionErrorMsg = optionErrorMsg, !optionErrorMsg.isEmpty {
            //Hud.showTip(optionErrorMsg)
            Hud.toast(str: optionErrorMsg)
        } else {
            Hud.toast(str: "NSFW materials have been detected, please upload other photos")
        }
    }
    
    @objc private func closeButtonAction() {
        closeAction?(self)
    }
}
