//
//  SelectCommonController.swift

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

import SnapKit
import UIKit

protocol SelectCommonModelProtocol: AnyObject {
    func displayStr() -> String

    func sourceObj() -> Any
}

class SelectCommonController: CLBaseViewController {
    // MARK: - Properties from header

    var vcTitle: String?
    var isMultiChoose: Bool = false
    var atlastSelectOne: Bool = false
    var cellClass: UITableViewCell.Type?
    var datas: [SelectCommonModelProtocol] = []
    var markSelected: [SelectCommonModelProtocol] = []
    var tapSingleAction: ((SelectCommonModelProtocol) -> Void)?
    var tapMultiConfrimAction: (([SelectCommonModelProtocol]) -> Void)?
    var specialCellForSignInFirstOption: SelectCommonModelProtocol?

    // MARK: - Private Properties

    private lazy var titleView: TitleView = {
        let view = TitleView()
        return view
    }()

    private lazy var tableView: UITableView = {
        let tableView = UITableView()
        tableView.separatorStyle = .none
        tableView.backgroundColor = .clear
        tableView.delegate = self
        tableView.dataSource = self
        tableView.contentInsetAdjustmentBehavior = .never
        tableView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: UIWindow.safeAreaBottom, right: 0)

        if let cellClass = cellClass {
            tableView.register(cellClass, forCellReuseIdentifier: String(describing: cellClass))
        } else {
            tableView.register(SelectCommonTableCell.self, forCellReuseIdentifier: String(describing: SelectCommonTableCell.self))
        }

        return tableView
    }()

    private var tempSelectModels: [SelectCommonModelProtocol] = []

    // MARK: - Lifecycle

    override func viewDidLoad() {
        super.viewDidLoad()
        setupUI()
        setupData()
        setupEvents()
    }

    // MARK: - Setup

    private func setupUI() {
        title = "Select"
        
        navigationView.setupBackButtonCloseIcon()

        view.addSubview(tableView)
        tableView.snp.makeConstraints { make in
            make.top.equalTo(navigationView.snp.bottom)
            make.left.right.bottom.equalToSuperview()
        }

        titleView.title = vcTitle
        titleView.frame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: titleView.preCalculateHeight())
        tableView.tableHeaderView = titleView

        if isMultiChoose {
            navigationView.styleMainButton.isHidden = false
            navigationView.styleMainButton.setTitle("Confirm", for: .normal)
            refreshMultiChooseConfirmBtn()
        }

        view.setNeedsDisplay()
        view.layoutIfNeeded()
    }

    private func tapNaviConfirm() {
        tapMultiConfrimAction?(tempSelectModels)
        markSelected = tempSelectModels
        dismiss(animated: true, completion: nil)
    }

    private func setupData() {
        if markSelected.count == 1, let firstSelected = markSelected.first,
           let index = datas.firstIndex(where: { $0 === firstSelected }) {
            tableView.scrollToRow(at: IndexPath(row: index, section: 0), at: .middle, animated: false)
        }

        tempSelectModels = markSelected.isEmpty ? [] : markSelected
    }

    private func setupEvents() {
    }

    // MARK: - Class Methods

    static func navController() -> CLNavigationController {
        let vc = SelectCommonController()
        return CLNavigationController(rootViewController: vc)
    }

    // MARK: - Helpers

    private func refreshMultiChooseConfirmBtn() {
        guard isMultiChoose else {
            assertionFailure("Should not call refreshMultiChooseConfirmBtn when not in multi-choose mode")
            return
        }
        navigationView.styleMainButton.isEnabled = atlastSelectOne ? !tempSelectModels.isEmpty : true
    }
}

// MARK: - UITableViewDelegate, UITableViewDataSource

extension SelectCommonController: UITableViewDelegate, UITableViewDataSource {
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return datas.count
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let data = datas[indexPath.row]

        if let cellClass = cellClass as? SelectCommonBaseCell.Type {
            let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: cellClass), for: indexPath) as! SelectCommonBaseCell
            cell.config(data: data)
            cell.configSelect(selected: markSelected.contains { $0 === data })
            return cell
        } else {
            let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: SelectCommonTableCell.self), for: indexPath) as! SelectCommonTableCell
            cell.isMultiChoose = isMultiChoose
            cell.config(data: data)
            cell.configSelect(selected: markSelected.contains { $0 === data })

            if let specialOption = specialCellForSignInFirstOption, specialOption === data {
                cell.configSignInFirstMode(true)
            } else {
                cell.configSignInFirstMode(false)
            }
            return cell
        }
    }

    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        let data = datas[indexPath.row]

        if specialCellForSignInFirstOption != nil && specialCellForSignInFirstOption === data {
            return
        }

        if isMultiChoose {
            if let index = tempSelectModels.firstIndex(where: { $0 === data }) {
                tempSelectModels.remove(at: index)
            } else {
                tempSelectModels.append(data)
            }
            markSelected = tempSelectModels
            tableView.reloadData()
            refreshMultiChooseConfirmBtn()
        } else {
            markSelected = [data]
            tapSingleAction?(data)
            dismiss(animated: true, completion: nil)
        }
    }

    func scrollViewDidScroll(_ scrollView: UIScrollView) {
        if !(vcTitle?.isEmpty ?? true) {
            NaviAlphaHandle.changeNaviTitleAlpha(scrollView: scrollView, titleLabel: navigationView.titleLabel)
        }
    }
}

// MARK: - SelectCommonModel

class SelectCommonModel: SelectCommonModelProtocol {
    var name: String?
    var objInfo: Any?
    var integerInfo: Int = 0

    func displayStr() -> String {
        return name ?? ""
    }

    func sourceObj() -> Any {
        return objInfo as Any
    }
}

class SelectCommonBaseCell: UITableViewCell {
    override func awakeFromNib() {
        super.awakeFromNib()
        // Initialization code
    }

    override func setSelected(_ selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)
        // Configure the view for the selected state
    }

    func config(data: SelectCommonModelProtocol) {
        // Base implementation, to be overridden by subclasses
    }

    func configSelect(selected: Bool) {
        // Base implementation, to be overridden by subclasses
    }
}

class SelectCommonTableCell: SelectCommonBaseCell {
    // MARK: - Properties

    private lazy var label: UILabel = {
        let label = UILabel()
        label.font = .t.tbl // EPSystemToken.typography(.bodyL).font
        label.numberOfLines = 0
        return label
    }()

    private lazy var checkButton: EPRadioButton = {
        let button = EPRadioButton()
        button.isUserInteractionEnabled = false
        button.isSelected = true
        return button
    }()

    private lazy var line: UIView = {
        let view = UIView()
        return view
    }()

    private lazy var signInFirstTipLabel: UILabel = {
        let label = UILabel()
        label.textColor = .c.cttn
        label.font = .t.tbs
        label.text = "Please Sign In"
        label.isHidden = true
        return label
    }()

    private var signInFirstMode: Bool = false

    var isMultiChoose: Bool = false {
        didSet {
            if isMultiChoose {
                checkButton.setupStyle(.rectangle)
            }
        }
    }

    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
        contentView.backgroundColor = .clear
        backgroundColor = .clear
        selectionStyle = .none
        initialViews()
    }

    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    override func awakeFromNib() {
        super.awakeFromNib()
        // Initialization code
    }

    override func setSelected(_ selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)
        // Configure the view for the selected state
    }

    // MARK: - Setup

    private func initialViews() {
        contentView.addSubview(checkButton)
        contentView.addSubview(label)
        contentView.addSubview(line)
        contentView.addSubview(signInFirstTipLabel)

        checkButton.snp.makeConstraints { make in
            make.size.equalTo(CGSize(width: 20, height: 20))
            make.right.equalToSuperview().offset(-24)
            make.centerY.equalToSuperview()
        }

        label.snp.makeConstraints { make in
            make.left.equalToSuperview().offset(24)
            make.top.equalToSuperview().offset(24)
            make.bottom.equalToSuperview().offset(-24)
            make.right.lessThanOrEqualTo(checkButton.snp.left).offset(-16)
        }

        line.snp.makeConstraints { make in
            make.leading.equalToSuperview().offset(24)
            make.trailing.equalToSuperview().offset(-24)
            make.bottom.equalToSuperview()
            make.height.equalTo(0.5)
        }

        signInFirstTipLabel.snp.makeConstraints { make in
            make.centerY.equalToSuperview()
            make.right.equalToSuperview().offset(-24)
        }

        label.textColor = .c.ctpn
        line.backgroundColor = .c.con
    }

    // MARK: - Public Methods

    override func config(data: SelectCommonModelProtocol) {
        label.text = data.displayStr()
    }

    override func configSelect(selected: Bool) {
        checkButton.isHidden = !selected
    }

    func configSignInFirstMode(_ mode: Bool) {
        signInFirstMode = mode
        if mode {
            label.textColor = .c.cttn
            signInFirstTipLabel.isHidden = false
        } else {
            label.textColor = .c.ctpn
            signInFirstTipLabel.isHidden = true
        }
    }
}
