import Foundation

/// エンジン状態管理
class EngineStateManager {
    
    // MARK: - Properties
    
    private(set) var currentState: EngineState = .notInitialized
    private let stateLock = NSLock()
    private var stateChangeHandlers: [(EngineState) -> Void] = []
    
    // MARK: - State Management
    
    /// 状態を変更
    func setState(_ newState: EngineState) {
        stateLock.lock()
        defer { stateLock.unlock() }
        
        let oldState = currentState
        currentState = newState
        
        // 状態変更ログは省略（デバッグ時のみ有効化）
        // print("[EngineState] \(oldState) → \(newState)")
        
        // 状態変更ハンドラーを呼び出し
        for handler in stateChangeHandlers {
            handler(newState)
        }
    }
    
    /// 現在の状態を取得
    func getState() -> EngineState {
        stateLock.lock()
        defer { stateLock.unlock() }
        return currentState
    }
    
    /// 状態変更ハンドラーを登録
    func onStateChange(_ handler: @escaping (EngineState) -> Void) {
        stateLock.lock()
        defer { stateLock.unlock() }
        stateChangeHandlers.append(handler)
    }
    
    // MARK: - State Validation
    
    /// 指定された状態への遷移が有効かチェック
    func canTransition(to newState: EngineState) -> Bool {
        stateLock.lock()
        defer { stateLock.unlock() }
        
        switch (currentState, newState) {
        case (.notInitialized, .initializing):
            return true
            
        case (.initializing, .ready):
            return true
            
        case (.initializing, .error):
            return true
            
        case (.ready, .analyzing):
            return true
            
        case (.ready, .notInitialized):
            return true  // シャットダウン
            
        case (.analyzing, .ready):
            return true
            
        case (.analyzing, .error):
            return true
            
        case (.error, .notInitialized):
            return true  // リセット
            
        case (.error, .initializing):
            return true  // 再初期化
            
        default:
            return false
        }
    }
    
    /// 状態遷移を試行
    func tryTransition(to newState: EngineState) -> Bool {
        if canTransition(to: newState) {
            setState(newState)
            return true
        } else {
            // 不正な状態遷移のみログ出力
            print("⚠️ [EngineState] Invalid transition: \(currentState) → \(newState)")
            return false
        }
    }
    
    /// エンジンが準備完了状態かチェック
    func isReady() -> Bool {
        stateLock.lock()
        defer { stateLock.unlock() }
        
        if case .ready = currentState {
            return true
        }
        return false
    }
    
    /// エンジンが解析中かチェック
    func isAnalyzing() -> Bool {
        stateLock.lock()
        defer { stateLock.unlock() }
        
        if case .analyzing = currentState {
            return true
        }
        return false
    }
    
    /// エンジンがエラー状態かチェック
    func isError() -> Bool {
        stateLock.lock()
        defer { stateLock.unlock() }
        
        if case .error = currentState {
            return true
        }
        return false
    }
}

// MARK: - Engine State

enum EngineState: Equatable {
    case notInitialized
    case initializing
    case ready
    case analyzing
    case error(String)
    
    static func == (lhs: EngineState, rhs: EngineState) -> Bool {
        switch (lhs, rhs) {
        case (.notInitialized, .notInitialized),
             (.initializing, .initializing),
             (.ready, .ready),
             (.analyzing, .analyzing):
            return true
        case (.error(let lhsMsg), .error(let rhsMsg)):
            return lhsMsg == rhsMsg
        default:
            return false
        }
    }
}

extension EngineState: CustomStringConvertible {
    var description: String {
        switch self {
        case .notInitialized:
            return "NotInitialized"
        case .initializing:
            return "Initializing"
        case .ready:
            return "Ready"
        case .analyzing:
            return "Analyzing"
        case .error(let message):
            return "Error(\(message))"
        }
    }
}
