//
//  HomeCollectionModels.swift
//  suixinkan
//

import Foundation
import UIKit

/// 首页 CollectionView 分区标识。
enum HomeCollectionSection: Hashable {
    case workStatus
    case locationReport
    case quickActions
    case store
    case commonApps
}

/// 首页 CollectionView 条目标识；各区块使用独立 case，避免 Diffable 去重。
enum HomeCollectionItem: Hashable {
    case workStatus
    case locationReport
    case quickActions
    case store
    case menu(HomeMenuItem)
}

/// 首页 CollectionView 布局与 snapshot 构建工具。
enum HomeCollectionLayoutBuilder {

    private static let menuColumns = 3
    private static let menuSpacing = AppSpacing.sm
    private static let sectionSpacing = AppSpacing.sm

    /// 构建 Compositional Layout，按当前分区类型返回 section 布局。
    static func makeLayout(sections: [HomeCollectionSection]) -> UICollectionViewCompositionalLayout {
        UICollectionViewCompositionalLayout { sectionIndex, environment in
            let section = sectionIndex < sections.count ? sections[sectionIndex] : .commonApps
            switch section {
            case .workStatus:
                return fullWidthSection(height: 84)
            case .locationReport:
                return fullWidthSection(height: 132)
            case .quickActions:
                return quickActionsSection(environment: environment)
            case .store:
                return fullWidthSection(height: 96)
            case .commonApps:
                return menuGridSection(environment: environment)
            }
        }
    }

    /// 根据 ViewModel 状态构建 Diffable Snapshot。
    static func makeSnapshot(
        showWorkBlock: Bool,
        showStore: Bool,
        storeItem: StoreItem?,
        commonMenus: [HomeMenuItem]
    ) -> NSDiffableDataSourceSnapshot<HomeCollectionSection, HomeCollectionItem> {
        var snapshot = NSDiffableDataSourceSnapshot<HomeCollectionSection, HomeCollectionItem>()

        if showWorkBlock {
            snapshot.appendSections([.workStatus, .locationReport, .quickActions])
            snapshot.appendItems([.workStatus], toSection: .workStatus)
            snapshot.appendItems([.locationReport], toSection: .locationReport)
            snapshot.appendItems([.quickActions], toSection: .quickActions)
        }

        if showStore, storeItem != nil {
            snapshot.appendSections([.store])
            snapshot.appendItems([.store], toSection: .store)
        }

        let menus = commonMenus + [HomeMenuItem.moreFunctions]
        snapshot.appendSections([.commonApps])
        snapshot.appendItems(menus.map { HomeCollectionItem.menu($0) }, toSection: .commonApps)

        return snapshot
    }

    /// 当前 snapshot 对应的分区顺序，供 layout 使用。
    static func sectionOrder(
        showWorkBlock: Bool,
        showStore: Bool,
        storeItem: StoreItem?
    ) -> [HomeCollectionSection] {
        var sections: [HomeCollectionSection] = []
        if showWorkBlock {
            sections.append(contentsOf: [.workStatus, .locationReport, .quickActions])
        }
        if showStore, storeItem != nil {
            sections.append(.store)
        }
        sections.append(.commonApps)
        return sections
    }

    private static let horizontalInset = AppSpacing.screenHorizontalInset

    private static func fullWidthSection(height: CGFloat) -> NSCollectionLayoutSection {
        let itemSize = NSCollectionLayoutSize(
            widthDimension: .fractionalWidth(1),
            heightDimension: .absolute(height)
        )
        let item = NSCollectionLayoutItem(layoutSize: itemSize)
        let groupSize = NSCollectionLayoutSize(
            widthDimension: .fractionalWidth(1),
            heightDimension: .absolute(height)
        )
        let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize, subitems: [item])
        let section = NSCollectionLayoutSection(group: group)
        section.contentInsets = NSDirectionalEdgeInsets(
            top: 0,
            leading: horizontalInset,
            bottom: sectionSpacing,
            trailing: horizontalInset
        )
        return section
    }

    private static func menuGridSection(environment: NSCollectionLayoutEnvironment) -> NSCollectionLayoutSection {
        let itemWidth = menuItemWidth(environment: environment)

        let itemSize = NSCollectionLayoutSize(
            widthDimension: .absolute(itemWidth),
            heightDimension: .absolute(itemWidth)
        )
        let item = NSCollectionLayoutItem(layoutSize: itemSize)
        let groupSize = NSCollectionLayoutSize(
            widthDimension: .fractionalWidth(1),
            heightDimension: .absolute(itemWidth)
        )
        let group = NSCollectionLayoutGroup.horizontal(
            layoutSize: groupSize,
            repeatingSubitem: item,
            count: menuColumns
        )
        group.interItemSpacing = .fixed(menuSpacing)

        let section = NSCollectionLayoutSection(group: group)
        section.interGroupSpacing = menuSpacing
        section.contentInsets = NSDirectionalEdgeInsets(
            top: 0,
            leading: horizontalInset,
            bottom: sectionSpacing,
            trailing: horizontalInset
        )

        let headerSize = NSCollectionLayoutSize(
            widthDimension: .fractionalWidth(1),
            heightDimension: .absolute(36)
        )
        let header = NSCollectionLayoutBoundarySupplementaryItem(
            layoutSize: headerSize,
            elementKind: UICollectionView.elementKindSectionHeader,
            alignment: .top
        )
        section.boundarySupplementaryItems = [header]
        return section
    }

    private static func quickActionsSection(environment: NSCollectionLayoutEnvironment) -> NSCollectionLayoutSection {
        fullWidthSection(height: menuItemWidth(environment: environment))
    }

    private static func menuItemWidth(environment: NSCollectionLayoutEnvironment) -> CGFloat {
        let availableWidth = environment.container.effectiveContentSize.width - horizontalInset * 2
        let totalSpacing = menuSpacing * CGFloat(menuColumns - 1)
        return max(0, (availableWidth - totalSpacing) / CGFloat(menuColumns))
    }
}
