import 'package:flutter/material.dart'; import '../../../../core/theme/app_theme.dart'; import '../models/trade_model.dart'; class TradeDetailModal extends StatelessWidget { final TradeModel trade; final VoidCallback? onAccept; final VoidCallback? onClose; const TradeDetailModal({ super.key, required this.trade, this.onAccept, this.onClose, }); static Future show( BuildContext context, { required TradeModel trade, VoidCallback? onAccept, VoidCallback? onClose, }) { return showModalBottomSheet( context: context, isScrollControlled: true, backgroundColor: Colors.transparent, builder: (ctx) => TradeDetailModal( trade: trade, onAccept: onAccept, onClose: onClose, ), ); } @override Widget build(BuildContext context) { final isBuy = trade.signalType == 'BUY'; final signalColor = isBuy ? AppTheme.primaryEmerald : AppTheme.accentRed; final pnlAbs = trade.calculatedPnlAbs; final pnlPct = trade.calculatedPnlPct; final isPnlPos = pnlAbs >= 0; final pnlColor = isPnlPos ? AppTheme.primaryEmerald : AppTheme.accentRed; final currPrice = trade.effectiveCurrentPrice; return Container( constraints: BoxConstraints(maxHeight: MediaQuery.of(context).size.height * 0.85), decoration: BoxDecoration( color: AppTheme.cardSurface, borderRadius: const BorderRadius.vertical(top: Radius.circular(24)), border: Border.all(color: Colors.white.withValues(alpha: 0.1)), boxShadow: [ BoxShadow( color: Colors.black.withValues(alpha: 0.6), blurRadius: 25, spreadRadius: 5, ) ], ), child: SafeArea( child: Column( mainAxisSize: MainAxisSize.min, children: [ // Handle Bar Container( margin: const EdgeInsets.symmetric(vertical: 12), width: 40, height: 4, decoration: BoxDecoration( color: Colors.white.withValues(alpha: 0.2), borderRadius: BorderRadius.circular(2), ), ), // Modal Header Padding( padding: const EdgeInsets.symmetric(horizontal: 20), child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ Container( padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6), decoration: BoxDecoration( color: signalColor.withValues(alpha: 0.18), borderRadius: BorderRadius.circular(10), border: Border.all(color: signalColor.withValues(alpha: 0.5)), ), child: Text( trade.signalType, style: TextStyle(color: signalColor, fontWeight: FontWeight.bold, fontSize: 14), ), ), const SizedBox(width: 12), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( trade.symbol.isNotEmpty && trade.symbol != 'UNKNOWN' ? trade.symbol : (trade.companyName.isNotEmpty && trade.companyName != 'UNKNOWN' ? trade.companyName : (trade.isin.isNotEmpty ? trade.isin : 'Aktie')), style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 20, color: Colors.white), ), if (trade.companyName.isNotEmpty && trade.companyName != trade.symbol && trade.companyName != 'UNKNOWN') Text( trade.companyName, style: TextStyle(color: AppTheme.textMuted, fontSize: 13), ), if (trade.isin.isNotEmpty || trade.sector.isNotEmpty) Text( '${trade.isin.isNotEmpty ? trade.isin : ""}${trade.isin.isNotEmpty && trade.sector.isNotEmpty ? " • " : ""}${trade.sector.isNotEmpty ? trade.sector : ""}', style: TextStyle(color: AppTheme.textMuted.withValues(alpha: 0.7), fontSize: 11), ), ], ), ), Container( padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 5), decoration: BoxDecoration( color: Colors.amber.withValues(alpha: 0.15), borderRadius: BorderRadius.circular(12), border: Border.all(color: Colors.amber.withValues(alpha: 0.4)), ), child: Row( children: [ const Icon(Icons.star, size: 14, color: Colors.amber), const SizedBox(width: 4), Text( '${trade.winRate.toStringAsFixed(0)}% Win-Rate', style: const TextStyle(color: Colors.amber, fontWeight: FontWeight.bold, fontSize: 11), ), ], ), ), ], ), ), const SizedBox(height: 16), const Divider(color: Colors.white10, height: 1), // Scrollable Content Expanded( child: SingleChildScrollView( padding: const EdgeInsets.all(20), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // Price Grid Container( padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: Colors.black.withValues(alpha: 0.3), borderRadius: BorderRadius.circular(14), border: Border.all(color: Colors.white.withValues(alpha: 0.08)), ), child: Row( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ _metricItem( trade.isActive || trade.isClosed ? 'Ausführung' : 'Ziel-Einstieg', trade.actualEntryPrice > 0 ? '${trade.actualEntryPrice.toStringAsFixed(2)} €' : (trade.entryPrice > 0 ? '${trade.entryPrice.toStringAsFixed(2)} €' : '-'), Colors.white ), _metricItem('Live-Kurs', '${currPrice.toStringAsFixed(2)} €', AppTheme.accentCyan), _metricItem('Stop-Loss', '${trade.stopLoss.toStringAsFixed(2)} €', AppTheme.accentRed), _metricItem('Take-Profit', '${trade.takeProfit.toStringAsFixed(2)} €', AppTheme.primaryEmerald), ], ), ), if (trade.isActive || trade.isClosed) ...[ const SizedBox(height: 14), Container( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), decoration: BoxDecoration( color: pnlColor.withValues(alpha: 0.12), borderRadius: BorderRadius.circular(12), border: Border.all(color: pnlColor.withValues(alpha: 0.3)), ), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ const Text('Aktueller PnL:', style: TextStyle(color: Colors.white70, fontSize: 13)), Text( '${isPnlPos ? '+' : ''}${pnlAbs.toStringAsFixed(2)} € (${isPnlPos ? '+' : ''}${pnlPct.toStringAsFixed(2)}%)', style: TextStyle(color: pnlColor, fontWeight: FontWeight.bold, fontSize: 15), ), ], ), ), ], const SizedBox(height: 20), // AI Reasoning Section if (trade.reasoning.isNotEmpty) ...[ _sectionTitle(Icons.auto_awesome, 'KI-Gesamteinschätzung & Begründung', AppTheme.primaryEmerald), const SizedBox(height: 8), Container( width: double.infinity, padding: const EdgeInsets.all(14), decoration: BoxDecoration( color: AppTheme.primaryEmerald.withValues(alpha: 0.08), borderRadius: BorderRadius.circular(12), border: Border.all(color: AppTheme.primaryEmerald.withValues(alpha: 0.2)), ), child: Text( trade.reasoning, style: const TextStyle(color: Colors.white, fontSize: 13, height: 1.4), ), ), const SizedBox(height: 18), ], // Technical Rationale Section if (trade.technicalRationale.isNotEmpty) ...[ _sectionTitle(Icons.show_chart, 'Technische Analyse & Indikatoren', AppTheme.accentCyan), const SizedBox(height: 8), Container( width: double.infinity, padding: const EdgeInsets.all(14), decoration: BoxDecoration( color: Colors.white.withValues(alpha: 0.03), borderRadius: BorderRadius.circular(12), border: Border.all(color: Colors.white.withValues(alpha: 0.08)), ), child: Text( trade.technicalRationale, style: TextStyle(color: AppTheme.textMuted, fontSize: 13, height: 1.4), ), ), const SizedBox(height: 18), ], // Fundamental Rationale Section if (trade.fundamentalRationale.isNotEmpty) ...[ _sectionTitle(Icons.account_balance, 'Fundamentale Bewertung', Colors.purpleAccent), const SizedBox(height: 8), Container( width: double.infinity, padding: const EdgeInsets.all(14), decoration: BoxDecoration( color: Colors.white.withValues(alpha: 0.03), borderRadius: BorderRadius.circular(12), border: Border.all(color: Colors.white.withValues(alpha: 0.08)), ), child: Text( trade.fundamentalRationale, style: TextStyle(color: AppTheme.textMuted, fontSize: 13, height: 1.4), ), ), const SizedBox(height: 18), ], // Risk Warning Section if (trade.riskWarning.isNotEmpty) ...[ _sectionTitle(Icons.warning_amber_rounded, 'Risikohinweis & Marktumfeld', AppTheme.accentRed), const SizedBox(height: 8), Container( width: double.infinity, padding: const EdgeInsets.all(14), decoration: BoxDecoration( color: AppTheme.accentRed.withValues(alpha: 0.1), borderRadius: BorderRadius.circular(12), border: Border.all(color: AppTheme.accentRed.withValues(alpha: 0.3)), ), child: Text( trade.riskWarning, style: TextStyle(color: AppTheme.accentRed, fontSize: 12, height: 1.4), ), ), const SizedBox(height: 18), ], // Trade Parameters Grid _sectionTitle(Icons.tune, 'Trade-Parameter & Instrument', Colors.white70), const SizedBox(height: 8), Container( padding: const EdgeInsets.all(14), decoration: BoxDecoration( color: Colors.white.withValues(alpha: 0.02), borderRadius: BorderRadius.circular(12), border: Border.all(color: Colors.white.withValues(alpha: 0.06)), ), child: Column( children: [ _paramRow('Instrument Typ:', trade.instrumentType.isNotEmpty ? trade.instrumentType : 'Stock'), if (trade.derivativeIsin.isNotEmpty) _paramRow('Derivat / Hebel ISIN:', trade.derivativeIsin), _paramRow('Zeithorizont:', trade.timeframe.isNotEmpty ? trade.timeframe : '1D'), if (trade.leverageUsed > 1) _paramRow('Hebel:', '${trade.leverageUsed.toStringAsFixed(0)}x'), if (trade.positionSize > 0) _paramRow('Positionsgröße:', '${trade.positionSize.toStringAsFixed(2)} €'), ], ), ), ], ), ), ), // Footer Action Bar Padding( padding: const EdgeInsets.all(16), child: Row( children: [ Expanded( child: OutlinedButton( onPressed: () => Navigator.pop(context), style: OutlinedButton.styleFrom( side: BorderSide(color: Colors.white.withValues(alpha: 0.2)), padding: const EdgeInsets.symmetric(vertical: 14), shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)), ), child: const Text('Schließen', style: TextStyle(color: Colors.white70)), ), ), if (trade.isProposed && onAccept != null) ...[ const SizedBox(width: 12), Expanded( flex: 2, child: ElevatedButton.icon( onPressed: () { Navigator.pop(context); onAccept!(); }, icon: const Icon(Icons.check_circle_outline, size: 18), label: const Text('Trade Übernehmen'), style: ElevatedButton.styleFrom( backgroundColor: AppTheme.primaryEmerald, foregroundColor: Colors.white, padding: const EdgeInsets.symmetric(vertical: 14), shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)), ), ), ), ], if (trade.isActive && onClose != null) ...[ const SizedBox(width: 12), Expanded( flex: 2, child: ElevatedButton.icon( onPressed: () { Navigator.pop(context); onClose!(); }, icon: const Icon(Icons.close, size: 18), label: const Text('Position Schließen'), style: ElevatedButton.styleFrom( backgroundColor: AppTheme.accentRed, foregroundColor: Colors.white, padding: const EdgeInsets.symmetric(vertical: 14), shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)), ), ), ), ], ], ), ), ], ), ), ); } Widget _sectionTitle(IconData icon, String title, Color color) { return Row( children: [ Icon(icon, size: 16, color: color), const SizedBox(width: 8), Text( title, style: TextStyle(color: color, fontWeight: FontWeight.bold, fontSize: 13), ), ], ); } Widget _metricItem(String label, String value, Color color) { return Column( children: [ Text(label, style: TextStyle(color: AppTheme.textMuted, fontSize: 11)), const SizedBox(height: 4), Text(value, style: TextStyle(color: color, fontWeight: FontWeight.bold, fontSize: 13)), ], ); } Widget _paramRow(String label, String value) { return Padding( padding: const EdgeInsets.symmetric(vertical: 4), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text(label, style: TextStyle(color: AppTheme.textMuted, fontSize: 12)), Text(value, style: const TextStyle(color: Colors.white, fontWeight: FontWeight.bold, fontSize: 12)), ], ), ); } }