//
// ScoreboardViewModel.swift
// IceGlass-iOS
//
// Copyright 2026 Rouslan Zenetl. All Rights Reserved.
//

import Foundation
import Observation

/// Bridges MainService → SwiftUI. Re-published whenever data lands so views
/// re-render. Owns refresh kick-off on scene activation and pull-to-refresh.
@Observable
@MainActor
final class ScoreboardViewModel {
    /// Bumped on every observer callback; views read it implicitly via the
    /// Observation framework so the entire tree re-evaluates.
    private var revision: Int = 0

    /// Tracks the most recent successful fetch time for the "Updated …" header.
    var lastUpdated: Date?

    /// Toggled by pull-to-refresh; views can show a spinner.
    var isRefreshing: Bool = false

    /// Settings — surfaced separately so the settings sheet can bind directly.
    var displayOption: AppSettings.DisplayOption {
        get {
            _ = revision
            return AppSettings.shared.displayOption
        }
        set {
            AppSettings.shared.displayOption = newValue
            revision += 1
        }
    }

    var gamesByDate: [Scoreboard.GameDay] {
        _ = revision
        return MainService.shared.gamesByDate
    }

    var roundSeriesGroups: [MainService.RoundGroup] {
        _ = revision
        return MainService.shared.roundSeriesGroups
    }

    /// Bridge object that forwards MainService callbacks back to this view model.
    /// Held strongly so MainService's weak observer reference stays alive.
    private var bridge: ObserverBridge?

    init() {}

    /// Wire this view model up to MainService. Idempotent; called from `.onAppear`.
    func attach() {
        guard bridge == nil else { return }
        let bridge = ObserverBridge { [weak self] in self?.handleUpdate() }
        self.bridge = bridge
        MainService.shared.observer = bridge
        // Initial sync — MainService may have already loaded a cached snapshot.
        handleUpdate()
    }

    private func handleUpdate() {
        lastUpdated = MainService.shared.lastUpdated
        revision += 1
    }

    func refreshNow() async {
        isRefreshing = true
        await MainService.shared.fetchAll()
        isRefreshing = false
    }

    func handleScenePhaseActive() {
        MainService.shared.resumePolling()
        Task { await refreshNow() }
    }

    func handleScenePhaseInactive() {
        MainService.shared.suspendPolling()
    }
}

/// Class adapter so MainService's `weak var observer` has something to hold;
/// @Observable view-model classes don't compose cleanly with weak refs.
@MainActor
private final class ObserverBridge: MainServiceObserver {
    private let onUpdate: () -> Void

    init(onUpdate: @escaping () -> Void) {
        self.onUpdate = onUpdate
    }

    func mainServiceDidUpdate() {
        onUpdate()
    }
}
