//
//  LNGameCategoryListView.swift
//  Lanu
//
//  Created by OneeChan on 2025/11/16.
//

import Foundation
import UIKit
import SnapKit


protocol LNGameCategoryListViewDelegate: AnyObject {
    func onCategoryListView(view: LNGameCategoryListView, didScrollTo category: LNGameTypeItemVO)
    func onCategoryListView(view: LNGameCategoryListView, didSelect topCategory: LNGameTypeItemVO, category: LNGameCategoryItemVO)
}
extension LNGameCategoryListViewDelegate {
    func onCategoryListView(view: LNGameCategoryListView, didScrollTo category: LNGameTypeItemVO) { }
    func onCategoryListView(view: LNGameCategoryListView, didSelect topCategory: LNGameTypeItemVO, category: LNGameCategoryItemVO) { }
}


class LNGameCategoryListView: UIView {
    private let columns = 3
    private let collectionViewLayout = UICollectionViewFlowLayout()
    private let collectionView: UICollectionView
    
    private var categories: [LNGameTypeItemVO] = []
    
    weak var delegate: LNGameCategoryListViewDelegate?
    
    override init(frame: CGRect) {
        collectionView = UICollectionView(frame: .zero, collectionViewLayout: collectionViewLayout)
        super.init(frame: frame)
        
        setupViews()
    }
    
    func update(categories: [LNGameTypeItemVO]) {
        self.categories = categories
        collectionView.reloadData()
        
        DispatchQueue.main.async { [weak self] in
            guard let self else { return }
            fixBottomSpace()
        }
    }
    
    func scrollTo(category: LNGameTypeItemVO) {
        guard let index = categories.firstIndex(where: { $0.code == category.code }) else {
            return
        }
        DispatchQueue.main.async { [weak self] in
            guard let self else { return }
            if let headerAttributes = collectionView.layoutAttributesForSupplementaryElement(
                ofKind: UICollectionView.elementKindSectionHeader,
                at: IndexPath(item: 0, section: index))
            {
                collectionView.setContentOffset(.init(x: 0, y: headerAttributes.frame.origin.y), animated: true)
            } else {
                collectionView.scrollToItem(at: .init(row: 0, section: index), at: .top, animated: true)
            }
        }
    }
    
    override func layoutSubviews() {
        super.layoutSubviews()
        
        let width = (bounds.width - collectionViewLayout.minimumInteritemSpacing) / CGFloat(columns) - collectionViewLayout.minimumInteritemSpacing
        collectionViewLayout.itemSize = .init(width: width, height: 68)
        
        DispatchQueue.main.async { [weak self] in
            guard let self else { return }
            fixBottomSpace()
        }
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

extension LNGameCategoryListView: UIScrollViewDelegate {
    func scrollViewDidScroll(_ scrollView: UIScrollView) {
        let offsetY = scrollView.contentOffset.y
        
        var section = 0
        for index in 0..<categories.count {
            if let headerAttributes = collectionView.layoutAttributesForSupplementaryElement(
                ofKind: UICollectionView.elementKindSectionHeader,
                at: IndexPath(item: 0, section: index)) {
                if offsetY >= headerAttributes.frame.origin.y {
                    section = index
                } else {
                    break
                }
            }
        }
        
        delegate?.onCategoryListView(view: self, didScrollTo: categories[section])
    }
}

extension LNGameCategoryListView: UICollectionViewDataSource, UICollectionViewDelegate {
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        categories[section].children.count
    }
    
    func numberOfSections(in collectionView: UICollectionView) -> Int {
        categories.count
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: LNGameCategoryListCell.className, for: indexPath) as! LNGameCategoryListCell
        
        let item = categories[indexPath.section].children[indexPath.row]
        cell.tabItemView.update(item)
        
        return cell
    }
    
    func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
        guard kind == UICollectionView.elementKindSectionHeader else {
            return UICollectionReusableView()
        }
        
        let view = collectionView.dequeueReusableSupplementaryView(ofKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: LNGameCategoryListHeader.className, for: indexPath) as! LNGameCategoryListHeader
        
        let section = categories[indexPath.section]
        view.update(section.name)
        
        return view
    }
    
    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        let category = categories[indexPath.section]
        let game = category.children[indexPath.row]
        delegate?.onCategoryListView(view: self, didSelect: category, category: game)
    }
}

extension LNGameCategoryListView {
    private func fixBottomSpace() {
        guard !categories.isEmpty else { return }
        if let headerAttributes = collectionView.layoutAttributesForSupplementaryElement(
            ofKind: UICollectionView.elementKindSectionHeader,
            at: IndexPath(item: 0, section: categories.count - 1)) {
            let offset = collectionView.contentSize.height - headerAttributes.frame.origin.y
            collectionView.contentInset = .init(top: 0, left: 0, bottom: bounds.height - offset, right: 0)
        }
    }
    
    private func setupViews() {
        collectionViewLayout.itemSize = .init(width: 77, height: 68)
        collectionViewLayout.minimumLineSpacing = 10
        collectionViewLayout.minimumInteritemSpacing = 12
        collectionViewLayout.headerReferenceSize = .init(width: 100, height: LNGameCategoryListHeader.height)
        collectionViewLayout.sectionInset = .init(top: 0, left: 12, bottom: 40, right: 12)
        
        collectionView.backgroundColor = .clear
        collectionView.dataSource = self
        collectionView.delegate = self
        collectionView.contentInsetAdjustmentBehavior = .never
        collectionView.showsHorizontalScrollIndicator = false
        collectionView.showsVerticalScrollIndicator = false
        collectionView.register(LNGameCategoryListCell.self, forCellWithReuseIdentifier: LNGameCategoryListCell.className)
        collectionView.register(LNGameCategoryListHeader.self, forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: LNGameCategoryListHeader.className)
        addSubview(collectionView)
        collectionView.snp.makeConstraints { make in
            make.edges.equalToSuperview()
        }
    }
}

private class LNGameCategoryListCell: UICollectionViewCell {
    let tabItemView = LNHomeGameTabItemView()
    override init(frame: CGRect) {
        super.init(frame: frame)
        
        contentView.addSubview(tabItemView)
        tabItemView.snp.makeConstraints { make in
            make.edges.equalToSuperview()
        }
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

private class LNGameCategoryListHeader: UICollectionReusableView {
    static let height = 36
    private let titleLabel = UILabel()
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        
        snp.makeConstraints { make in
            make.height.equalTo(Self.height)
        }
        
        titleLabel.font = .heading_h2
        titleLabel.textColor = .text_5
        addSubview(titleLabel)
        titleLabel.snp.makeConstraints { make in
            make.bottom.equalToSuperview().offset(-8)
            make.leading.equalToSuperview().offset(10)
        }
    }
    
    func update(_ title: String) {
        titleLabel.text = title
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}


#if DEBUG

import SwiftUI

struct LNGameCategoryListViewPreview: UIViewRepresentable {
    func makeUIView(context: Context) -> some UIView {
        let container = UIView()
        container.backgroundColor = .lightGray
        
        let view = LNGameCategoryListView()
        container.addSubview(view)
        view.snp.makeConstraints { make in
            make.leading.top.trailing.equalToSuperview()
        }
        
        return container
    }
    
    func updateUIView(_ uiView: UIViewType, context: Context) { }
}

#Preview(body: {
    LNGameCategoryListViewPreview()
})
#endif
