import Foundation

/// Request for registering context state changes (model status, clip status, etc.)
public struct ContextStateRequest: Codable, Equatable {
    public let sessionId: String
    public let type: ContextStateType
    public let metadata: ContextStateMetadata
    
    public init(sessionId: String, type: ContextStateType, metadata: ContextStateMetadata) {
        self.sessionId = sessionId
        self.type = type
        self.metadata = metadata
    }
    
    private enum CodingKeys: String, CodingKey {
        case sessionId = "session_id"
        case type
        case metadata
    }
}

/// Types of context state that can be registered
public enum ContextStateType: String, Codable {
    case clipStatus = "clip_status"
    case modelStatus = "model_status"
}

/// Metadata for context state requests.
/// Each state type has its own specific metadata structure.
public enum ContextStateMetadata: Codable, Equatable {
    case clipStatus(ClipStatusMetadata)
    case modelStatus(ModelStatusMetadata)
    
    /// Metadata for clip status updates
    public struct ClipStatusMetadata: Codable, Equatable {
        public let clipId: String
        public let status: String
        public let duration: Double
        
        public init(clipId: String, status: String, duration: Double) {
            self.clipId = clipId
            self.status = status
            self.duration = duration
        }
        
        private enum CodingKeys: String, CodingKey {
            case clipId = "clip_id"
            case status
            case duration
        }
    }
    
    /// Metadata for model status updates
    public struct ModelStatusMetadata: Codable, Equatable {
        public let modelName: String
        
        public init(modelName: String) {
            self.modelName = modelName
        }
        
        private enum CodingKeys: String, CodingKey {
            case modelName = "model_name"
        }
    }
    
    // MARK: - Codable Implementation
    
    public init(from decoder: Decoder) throws {
        // Try to decode as ClipStatusMetadata first (has clip_id, status, duration)
        if let clipStatus = try? ClipStatusMetadata(from: decoder) {
            self = .clipStatus(clipStatus)
        } else if let modelStatus = try? ModelStatusMetadata(from: decoder) {
            // Try to decode as ModelStatusMetadata (has model_name)
            self = .modelStatus(modelStatus)
        } else {
            throw DecodingError.dataCorrupted(
                DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Unable to decode ContextStateMetadata")
            )
        }
    }
    
    public func encode(to encoder: Encoder) throws {
        switch self {
        case .clipStatus(let metadata):
            try metadata.encode(to: encoder)
        case .modelStatus(let metadata):
            try metadata.encode(to: encoder)
        }
    }
}

/// Request for registering a new session with a workspace
public struct RegisterSessionRequest: Codable, Equatable {
    public let sessionId: String
    public let workspaceId: String
    public let creationSource: String?
    
    public init(sessionId: String, workspaceId: String, creationSource: String? = nil) {
        self.sessionId = sessionId
        self.workspaceId = workspaceId
        self.creationSource = creationSource
    }
    
    private enum CodingKeys: String, CodingKey {
        case sessionId = "session_id"
        case workspaceId = "workspace_id"
        case creationSource = "creation_source"
    }
}

