//
//  DateRangePickerViewController.swift
//  suixinkan
//

import SnapKit
import UIKit

/// 通用日期范围选择 Sheet，从 Statistics 抽取，对齐 Android `DateRangeBottomSheet`。
final class DateRangePickerViewController: UIViewController {

    var onShortcutSelected: ((String) -> Void)?
    var onRangeSelected: ((Date, Date) -> Void)?

    private var currentMonth: Date
    private var tempStart: Date?
    private var tempEnd: Date?
    private var selectedShortcut: String?

    private let shortcutStack = UIStackView()
    private let monthTitleLabel = UILabel()
    private let weekdayStack = UIStackView()
    private let daysCollectionView: UICollectionView
    private var shortcutButtons: [StatisticsPeriodButton] = []

    private let calendar: Calendar = {
        var calendar = Calendar(identifier: .gregorian)
        calendar.locale = Locale(identifier: "zh_CN")
        calendar.firstWeekday = 2
        return calendar
    }()

    init(rangeStart: Date?, rangeEnd: Date?) {
        self.tempStart = rangeStart
        self.tempEnd = rangeEnd
        self.currentMonth = rangeStart ?? Date()

        let layout = UICollectionViewFlowLayout()
        layout.minimumInteritemSpacing = 0
        layout.minimumLineSpacing = 8
        daysCollectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)

        let today = Calendar.current.startOfDay(for: Date())
        let initCalendar = Calendar(identifier: .gregorian)
        if rangeStart == nil, rangeEnd == nil {
            selectedShortcut = StatisticsRangeShortcut.all.rawValue
        } else if rangeStart == today, rangeEnd == today {
            selectedShortcut = StatisticsRangeShortcut.today.rawValue
        } else if
            let start = rangeStart,
            let end = rangeEnd,
            start == initCalendar.date(byAdding: .day, value: -1, to: today),
            end == initCalendar.date(byAdding: .day, value: -1, to: today) {
            selectedShortcut = StatisticsRangeShortcut.yesterday.rawValue
        } else if
            let start = rangeStart,
            let end = rangeEnd,
            start == initCalendar.date(byAdding: .day, value: -6, to: today),
            end == today {
            selectedShortcut = StatisticsRangeShortcut.last7Days.rawValue
        }

        super.init(nibName: nil, bundle: nil)
    }

    @available(*, unavailable)
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .white
        setupUI()
        updateMonthTitle()
    }

    private func setupUI() {
        shortcutStack.axis = .horizontal
        shortcutStack.distribution = .equalSpacing

        StatisticsRangeShortcut.allCases.forEach { shortcut in
            let button = StatisticsPeriodButton()
            button.cornerStyle = .fixed(10)
            button.periodTitle = shortcut.rawValue
            button.isSelected = shortcut.rawValue == selectedShortcut
            button.addTarget(self, action: #selector(shortcutTapped(_:)), for: .touchUpInside)
            shortcutButtons.append(button)
            shortcutStack.addArrangedSubview(button)
        }

        let previousButton = UIButton(type: .system)
        previousButton.setImage(UIImage(systemName: "chevron.left"), for: .normal)
        previousButton.tintColor = UIColor(hex: 0x9CA3AF)
        previousButton.addTarget(self, action: #selector(previousMonth), for: .touchUpInside)

        let nextButton = UIButton(type: .system)
        nextButton.setImage(UIImage(systemName: "chevron.right"), for: .normal)
        nextButton.tintColor = UIColor(hex: 0x9CA3AF)
        nextButton.addTarget(self, action: #selector(nextMonth), for: .touchUpInside)

        monthTitleLabel.font = .systemFont(ofSize: 16, weight: .semibold)
        monthTitleLabel.textAlignment = .center

        let monthRow = UIStackView(arrangedSubviews: [previousButton, monthTitleLabel, nextButton])
        monthRow.axis = .horizontal
        monthRow.alignment = .center
        monthRow.distribution = .equalCentering

        weekdayStack.axis = .horizontal
        weekdayStack.distribution = .fillEqually
        ["一", "二", "三", "四", "五", "六", "日"].forEach { title in
            let label = UILabel()
            label.text = title
            label.font = .systemFont(ofSize: 12)
            label.textColor = UIColor(hex: 0x9CA3AF)
            label.textAlignment = .center
            weekdayStack.addArrangedSubview(label)
        }

        daysCollectionView.backgroundColor = .clear
        daysCollectionView.dataSource = self
        daysCollectionView.delegate = self
        daysCollectionView.register(DateCell.self, forCellWithReuseIdentifier: DateCell.reuseIdentifier)

        view.addSubview(shortcutStack)
        view.addSubview(monthRow)
        view.addSubview(weekdayStack)
        view.addSubview(daysCollectionView)

        shortcutStack.snp.makeConstraints { make in
            make.top.equalTo(view.safeAreaLayoutGuide).offset(12)
            make.leading.trailing.equalToSuperview().inset(16)
            make.height.equalTo(36)
        }
        monthRow.snp.makeConstraints { make in
            make.top.equalTo(shortcutStack.snp.bottom).offset(12)
            make.leading.trailing.equalToSuperview().inset(16)
            make.height.equalTo(32)
        }
        previousButton.snp.makeConstraints { make in
            make.size.equalTo(24)
        }
        nextButton.snp.makeConstraints { make in
            make.size.equalTo(24)
        }
        weekdayStack.snp.makeConstraints { make in
            make.top.equalTo(monthRow.snp.bottom).offset(8)
            make.leading.trailing.equalToSuperview().inset(16)
        }
        daysCollectionView.snp.makeConstraints { make in
            make.top.equalTo(weekdayStack.snp.bottom).offset(8)
            make.leading.trailing.equalToSuperview().inset(16)
            make.bottom.equalTo(view.safeAreaLayoutGuide).inset(16)
            make.height.equalTo(240)
        }
    }

    @objc private func shortcutTapped(_ sender: StatisticsPeriodButton) {
        onShortcutSelected?(sender.periodTitle)
    }

    @objc private func previousMonth() {
        currentMonth = calendar.date(byAdding: .month, value: -1, to: currentMonth) ?? currentMonth
        updateMonthTitle()
        daysCollectionView.reloadData()
    }

    @objc private func nextMonth() {
        currentMonth = calendar.date(byAdding: .month, value: 1, to: currentMonth) ?? currentMonth
        updateMonthTitle()
        daysCollectionView.reloadData()
    }

    private func updateMonthTitle() {
        let components = calendar.dateComponents([.year, .month], from: currentMonth)
        monthTitleLabel.text = "\(components.year ?? 0)年\(components.month ?? 0)月"
    }

    private func monthDates() -> [Date?] {
        guard
            let monthStart = calendar.date(from: calendar.dateComponents([.year, .month], from: currentMonth)),
            let dayRange = calendar.range(of: .day, in: .month, for: monthStart)
        else {
            return []
        }

        let firstWeekday = calendar.component(.weekday, from: monthStart)
        let leadingEmpty = (firstWeekday + 5) % 7
        var dates: [Date?] = Array(repeating: nil, count: leadingEmpty)
        for day in dayRange {
            if let date = calendar.date(byAdding: .day, value: day - 1, to: monthStart) {
                dates.append(date)
            }
        }
        while dates.count % 7 != 0 {
            dates.append(nil)
        }
        return dates
    }

    private func handleDateTap(_ date: Date) {
        selectedShortcut = nil
        shortcutButtons.forEach { $0.isSelected = false }

        if tempStart == nil || (tempStart != nil && tempEnd != nil) {
            tempStart = date
            tempEnd = nil
        } else if let start = tempStart {
            if date < start {
                tempEnd = start
                tempStart = date
            } else {
                tempEnd = date
            }
            if let start = tempStart, let end = tempEnd {
                onRangeSelected?(start, end)
            }
        }
        daysCollectionView.reloadData()
    }

    private func isInRange(_ date: Date) -> Bool {
        guard let start = tempStart else { return false }
        if let end = tempEnd {
            return date >= min(start, end) && date <= max(start, end)
        }
        return calendar.isDate(date, inSameDayAs: start)
    }

    private final class DateCell: UICollectionViewCell {
        static let reuseIdentifier = "DateRangePickerDateCell"

        private let label = UILabel()

        override init(frame: CGRect) {
            super.init(frame: frame)
            label.textAlignment = .center
            label.font = .systemFont(ofSize: 14)
            contentView.addSubview(label)
            label.snp.makeConstraints { make in
                make.edges.equalToSuperview()
            }
            contentView.layer.cornerRadius = 16
            contentView.clipsToBounds = true
        }

        @available(*, unavailable)
        required init?(coder: NSCoder) {
            fatalError("init(coder:) has not been implemented")
        }

        func configure(text: String?, selected: Bool, inRange: Bool) {
            label.text = text
            if selected {
                contentView.backgroundColor = AppColor.primary
                label.textColor = .white
            } else if inRange {
                contentView.backgroundColor = UIColor(hex: 0xEFF6FF)
                label.textColor = AppColor.primary
            } else {
                contentView.backgroundColor = .clear
                label.textColor = .black
            }
        }
    }
}

extension DateRangePickerViewController: UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        monthDates().count
    }

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(
            withReuseIdentifier: DateCell.reuseIdentifier,
            for: indexPath
        ) as! DateCell
        let dates = monthDates()
        guard indexPath.item < dates.count, let date = dates[indexPath.item] else {
            cell.configure(text: nil, selected: false, inRange: false)
            return cell
        }
        let day = calendar.component(.day, from: date)
        let selected = (tempStart != nil && calendar.isDate(date, inSameDayAs: tempStart!))
            || (tempEnd != nil && calendar.isDate(date, inSameDayAs: tempEnd!))
        cell.configure(text: "\(day)", selected: selected, inRange: isInRange(date))
        return cell
    }

    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        let dates = monthDates()
        guard indexPath.item < dates.count, let date = dates[indexPath.item] else { return }
        handleDateTap(date)
    }

    func collectionView(
        _ collectionView: UICollectionView,
        layout collectionViewLayout: UICollectionViewLayout,
        sizeForItemAt indexPath: IndexPath
    ) -> CGSize {
        let width = collectionView.bounds.width / 7
        return CGSize(width: width, height: 32)
    }
}

/// Statistics 模块兼容别名。
typealias StatisticsDateRangeViewController = DateRangePickerViewController
