enum MessageRole { user, assistant, system }

enum MessageType { text, toolUse, toolResult, approval, thinking, standingOrderDraft, interrupted }

enum ToolStatus { executing, completed, error, blocked, awaitingApproval }

class ChatAttachment {
  final String base64Data;
  final String mediaType;
  final String? fileName;

  const ChatAttachment({
    required this.base64Data,
    required this.mediaType,
    this.fileName,
  });

  Map<String, dynamic> toJson() => {
    'base64Data': base64Data,
    'mediaType': mediaType,
    if (fileName != null) 'fileName': fileName,
  };
}

class ChatMessage {
  final String id;
  final MessageRole role;
  final String content;
  final DateTime timestamp;
  final MessageType? type;
  final ToolExecution? toolExecution;
  final ApprovalRequest? approvalRequest;
  final bool isStreaming;
  final Map<String, dynamic>? metadata;
  final List<ChatAttachment>? attachments;

  const ChatMessage({
    required this.id,
    required this.role,
    required this.content,
    required this.timestamp,
    this.type,
    this.toolExecution,
    this.approvalRequest,
    this.isStreaming = false,
    this.metadata,
    this.attachments,
  });

  ChatMessage copyWith({
    String? id,
    MessageRole? role,
    String? content,
    DateTime? timestamp,
    MessageType? type,
    ToolExecution? toolExecution,
    ApprovalRequest? approvalRequest,
    bool? isStreaming,
    Map<String, dynamic>? metadata,
    List<ChatAttachment>? attachments,
  }) {
    return ChatMessage(
      id: id ?? this.id,
      role: role ?? this.role,
      content: content ?? this.content,
      timestamp: timestamp ?? this.timestamp,
      type: type ?? this.type,
      toolExecution: toolExecution ?? this.toolExecution,
      approvalRequest: approvalRequest ?? this.approvalRequest,
      isStreaming: isStreaming ?? this.isStreaming,
      metadata: metadata ?? this.metadata,
      attachments: attachments ?? this.attachments,
    );
  }
}

class ToolExecution {
  final String toolName;
  final String input;
  final String? output;
  final int riskLevel;
  final ToolStatus status;

  const ToolExecution({
    required this.toolName,
    required this.input,
    this.output,
    required this.riskLevel,
    required this.status,
  });

  ToolExecution copyWith({String? output, ToolStatus? status}) {
    return ToolExecution(
      toolName: toolName,
      input: input,
      output: output ?? this.output,
      riskLevel: riskLevel,
      status: status ?? this.status,
    );
  }
}

class ApprovalRequest {
  final String taskId;
  final String command;
  final int riskLevel;
  final String? targetServer;
  final DateTime expiresAt;
  final String? status;

  const ApprovalRequest({
    required this.taskId,
    required this.command,
    required this.riskLevel,
    this.targetServer,
    required this.expiresAt,
    this.status,
  });
}
