import 'package:equatable/equatable.dart'; import '../models/bot_models.dart'; abstract class BotState extends Equatable { const BotState(); @override List get props => []; } class BotInitial extends BotState { const BotInitial(); } class BotLoading extends BotState { const BotLoading(); } class BotLoaded extends BotState { final BotStatusModel status; final AccountSummaryModel summary; final List positions; final bool isPanicClosing; final String? actionMessage; /// True when [actionMessage] describes a failure or a partial success (e.g. a panic-close that could not /// confirm every position was closed) rather than a full, unqualified success - the UI must not present /// this the same way as a genuine success (Rules.md ยง4). final bool actionIsWarning; const BotLoaded({ required this.status, required this.summary, required this.positions, this.isPanicClosing = false, this.actionMessage, this.actionIsWarning = false, }); int get activePositionsCount => positions.where((p) => p.isActive).length; double get totalUnrealizedPnL => positions.where((p) => p.isActive).fold(0.0, (sum, p) => sum + p.unrealizedPnlEur); double get totalRealizedPnL => positions.fold(0.0, (sum, p) => sum + p.realizedPnlEur); BotLoaded copyWith({ BotStatusModel? status, AccountSummaryModel? summary, List? positions, bool? isPanicClosing, String? actionMessage, bool actionIsWarning = false, }) { return BotLoaded( status: status ?? this.status, summary: summary ?? this.summary, positions: positions ?? this.positions, isPanicClosing: isPanicClosing ?? this.isPanicClosing, actionMessage: actionMessage, actionIsWarning: actionIsWarning, ); } @override List get props => [status, summary, positions, isPanicClosing, actionMessage, actionIsWarning]; } class BotError extends BotState { final String message; const BotError(this.message); @override List get props => [message]; }