//
//  GameStateViewModel.swift
//  lichunWebsocket
//
//  Manages cross-feature game state (energy, money, time, etc.)
//

import Foundation
import Combine
import SwiftUI

class GameStateViewModel: ObservableObject {
    // MARK: - Published Properties

    // Resources
    @Published var energy: Int = 100
    @Published var money: Int = 0
    @Published var diamonds: Int = 0

    // Time & Date
    @Published var gameDate: String = ""
    @Published var hourOfDay: Int = 8
    @Published var minuteOfHour: Int = 0
    @Published var season: String = "spring"

    // Game State
    @Published var gameSpeed: Int = Constants.GameSpeed.normal
    @Published var status: String = ""
    @Published var location: String = ""

    // UI State
    @Published var intraDayMessage: String = ""
    @Published var mood: String = ""
    
    // Health Stats
    @Published var health: Int = 100
    @Published var happiness: Int = 50
    @Published var stress: Int = 0
    @Published var hunger: Int = 0
    @Published var thirst: Int = 0
    @Published var intelligence: Int = 50
    @Published var ageYears: Int = 0

    // MARK: - Private Properties
    private var webSocketService: WebSocketService
    private var cancellables = Set<AnyCancellable>()

    // MARK: - Initialization
    init(webSocketService: WebSocketService) {
        self.webSocketService = webSocketService
        setupBindings()
    }

    // MARK: - Setup
    private func setupBindings() {
        // Subscribe to WebSocketService updates
        webSocketService.gameState.$person
            .sink { [weak self] person in
                self?.energy = person.calcEnergy
                self?.money = person.money
                self?.diamonds = person.diamonds
                self?.location = person.location
                self?.status = person.status
                self?.intraDayMessage = person.intraDayMessage
                self?.mood = person.mood
                self?.health = person.health
                self?.happiness = person.happiness
                self?.stress = person.stress
                self?.hunger = person.hunger
                self?.thirst = person.thirst
                self?.intelligence = person.intelligence
                self?.ageYears = person.ageYears
            }
            .store(in: &cancellables)

        webSocketService.gameState.$player
            .sink { [weak self] player in
                self?.gameDate = player.date
                self?.hourOfDay = player.hourOfDay
                self?.minuteOfHour = player.minuteOfHour
                self?.gameSpeed = player.gameSpeed
                self?.season = player.season
                if !player.status.isEmpty {
                    self?.status = player.status
                }
            }
            .store(in: &cancellables)
    }

    // MARK: - Public Methods

    /// Check if the player can afford a given cost
    func canAfford(energy: Int = 0, money: Int = 0, diamonds: Int = 0) -> Bool {
        return self.energy >= energy && self.money >= money && self.diamonds >= diamonds
    }

    /// Set the game speed
    func setGameSpeed(_ speed: Int) {
        webSocketService.sendMessage(message: WebSocketCommands.speed(speed))
    }

    /// Get formatted time string
    var formattedTime: String {
        let hour = hourOfDay % 12 == 0 ? 12 : hourOfDay % 12
        let period = hourOfDay >= 12 ? "PM" : "AM"
        return String(format: "%d:%02d %@", hour, minuteOfHour, period)
    }

    /// Get time of day description
    var timeOfDayDescription: String {
        switch hourOfDay {
        case 0..<6:
            return "Late Night"
        case 6..<12:
            return "Morning"
        case 12..<17:
            return "Afternoon"
        case 17..<21:
            return "Evening"
        default:
            return "Night"
        }
    }

    /// Get season emoji
    var seasonEmoji: String {
        switch season.lowercased() {
        case "spring":
            return "🌸"
        case "summer":
            return "☀️"
        case "autumn", "fall":
            return "🍂"
        case "winter":
            return "❄️"
        default:
            return "🌍"
        }
    }

    /// Check if it's a specific time of day
    func isTimeOfDay(_ timeRange: ClosedRange<Int>) -> Bool {
        return timeRange.contains(hourOfDay)
    }
}
