import 'package:flutter/material.dart'; import '../../../../core/theme/app_theme.dart'; import '../models/trade_model.dart'; class TradeCalculationCard extends StatelessWidget { final TradeModel trade; final bool initiallyExpanded; final bool isCollapsible; const TradeCalculationCard({ super.key, required this.trade, this.initiallyExpanded = true, this.isCollapsible = false, }); @override Widget build(BuildContext context) { final entry = trade.averageBuyIn; final quantity = trade.totalQuantity; final posSize = entry * quantity; final isShort = !trade.direction.isLong; // Distance-to-stop risk, computed only from real DTO fields (averageBuyIn, // currentStopLoss, totalQuantity) — no fee/leverage assumptions are // invented since ActiveTradeDto no longer carries either (Rules.md §4). final sl = trade.currentStopLoss; final riskAmountAbs = (isShort ? (sl - entry) : (entry - sl)).abs() * quantity; // Reward-to-target(s), same principle. final stages = trade.exitPlan.takeProfitStages; final primaryTp = trade.primaryTakeProfit; final rewardAmountAbs = primaryTp != null ? (isShort ? (entry - primaryTp) : (primaryTp - entry)).abs() * quantity : null; final crv = (rewardAmountAbs != null && riskAmountAbs > 0) ? (rewardAmountAbs / riskAmountAbs) : null; final content = Container( padding: const EdgeInsets.all(14), decoration: BoxDecoration( color: Colors.black.withValues(alpha: 0.3), borderRadius: BorderRadius.circular(14), border: Border.all(color: Colors.white.withValues(alpha: 0.08)), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ _statTile( 'Stückzahl', '${quantity.toStringAsFixed(2)} Stk.', Colors.white, ), _statTile( 'Risiko bis Stop-Loss', '-€${riskAmountAbs.toStringAsFixed(2)}', AppTheme.accentRed, ), _statTile( 'Potenzial bis 1. Ziel', rewardAmountAbs != null ? '+€${rewardAmountAbs.toStringAsFixed(2)}' : 'Trailing-Exit', AppTheme.primaryEmerald, ), _statTile( 'Chance-Risiko (CRV)', crv != null ? '1 : ${crv.toStringAsFixed(2)}' : '-', AppTheme.accentCyan, ), ], ), const Divider(color: Colors.white10, height: 16), Text( 'Investiertes Kapital: €${posSize.toStringAsFixed(2)} • Exit-Strategie: ${trade.exitPlan.strategyType.label}', style: TextStyle(color: AppTheme.textMuted, fontSize: 11), ), if (stages.length > 1) ...[ const Divider(color: Colors.white10, height: 16), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( '🎯 MEHRSTUFIGE GEWINN-KALKULATION', style: TextStyle( color: AppTheme.primaryEmerald, fontSize: 11, fontWeight: FontWeight.w900, letterSpacing: 0.5, ), ), Text( '${stages.length} Ziele', style: TextStyle(color: AppTheme.textMuted, fontSize: 10), ), ], ), const SizedBox(height: 8), ...stages.map((stage) { final targetPrice = stage.targetPrice; final isCurrent = primaryTp != null && (primaryTp - targetPrice).abs() < 0.001; final targetMove = (isShort ? (entry - targetPrice) : (targetPrice - entry)); final netTargetProfit = targetMove * quantity; final cappedNet = netTargetProfit > 0 ? netTargetProfit : 0.0; final retPct = posSize > 0 ? (cappedNet / posSize * 100) : 0.0; final targetCrv = (riskAmountAbs > 0 && cappedNet > 0) ? (cappedNet / riskAmountAbs) : 0.0; final baseMove = entry > 0 ? (targetMove / entry * 100).abs() : 0.0; return Container( margin: const EdgeInsets.only(bottom: 6), padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 8), decoration: BoxDecoration( color: isCurrent ? AppTheme.primaryEmerald.withValues(alpha: 0.14) : Colors.white.withValues(alpha: 0.03), borderRadius: BorderRadius.circular(8), border: Border.all( color: isCurrent ? AppTheme.primaryEmerald.withValues(alpha: 0.7) : Colors.white.withValues(alpha: 0.07), width: isCurrent ? 1.5 : 1, ), ), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Row( children: [ Container( padding: const EdgeInsets.symmetric( horizontal: 6, vertical: 2), decoration: BoxDecoration( color: isCurrent ? AppTheme.primaryEmerald : Colors.white12, borderRadius: BorderRadius.circular(4), ), child: Text( 'TP${stage.stageNumber}', style: TextStyle( color: isCurrent ? Colors.black : Colors.white, fontSize: 10, fontWeight: FontWeight.w900, ), ), ), const SizedBox(width: 8), Text( '€${targetPrice.toStringAsFixed(2)}', style: const TextStyle( color: Colors.white, fontSize: 12, fontWeight: FontWeight.bold, ), ), const SizedBox(width: 6), Text( '(+${baseMove.toStringAsFixed(1)}% Basiswert)', style: TextStyle( color: AppTheme.textMuted, fontSize: 10.5), ), ], ), Column( crossAxisAlignment: CrossAxisAlignment.end, children: [ Text( '+€${cappedNet.toStringAsFixed(2)} (+${retPct.toStringAsFixed(1)}%)', style: TextStyle( color: isCurrent ? AppTheme.primaryEmerald : Colors.white, fontSize: 12, fontWeight: FontWeight.w900, ), ), if (targetCrv > 0) Text( 'CRV 1 : ${targetCrv.toStringAsFixed(2)}', style: TextStyle( color: isCurrent ? AppTheme.primaryEmerald : AppTheme.accentCyan, fontSize: 10, fontWeight: FontWeight.bold, ), ), ], ), ], ), ); }), ], ], ), ); if (!isCollapsible) { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text( '3. LIVE-KALKULATION (AUTOMATISCH)', style: TextStyle( color: Colors.white, fontSize: 12, fontWeight: FontWeight.w900, letterSpacing: 0.5, ), ), const SizedBox(height: 8), content, ], ); } return Theme( data: ThemeData(dividerColor: Colors.transparent), child: ExpansionTile( initiallyExpanded: initiallyExpanded, tilePadding: EdgeInsets.zero, childrenPadding: EdgeInsets.zero, dense: true, iconColor: AppTheme.primaryEmerald, collapsedIconColor: Colors.white70, title: Row( children: [ Icon(Icons.calculate_outlined, color: AppTheme.primaryEmerald, size: 16), const SizedBox(width: 8), const Text( 'Live-Kalkulation & Gewinn-Potenzial', style: TextStyle( color: Colors.white, fontSize: 13, fontWeight: FontWeight.bold, ), ), ], ), children: [ content, ], ), ); } Widget _statTile(String label, String value, Color col) { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(label, style: TextStyle(color: AppTheme.textMuted, fontSize: 10)), const SizedBox(height: 2), Text(value, style: TextStyle( color: col, fontWeight: FontWeight.bold, fontSize: 12.5)), ], ); } }