import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import '../models/history_entry_model.dart'; import '../services/ai_oracle_service.dart'; import '../services/words_repository.dart'; import '../widgets/gradient_star_badge.dart'; class SessionResultScreen extends StatefulWidget { final OracleSession session; const SessionResultScreen({ super.key, required this.session, }); @override State createState() => _SessionResultScreenState(); } class _SessionResultScreenState extends State { final _aiService = AiOracleService(); final _repo = WordsRepository(); late OracleSession _session; bool _isLoadingAi = false; @override void initState() { super.initState(); _session = widget.session; // Persist the session atomically _repo.saveSession(_session); } Future _fetchAiInterpretation() async { setState(() => _isLoadingAi = true); HapticFeedback.mediumImpact(); try { final result = await _aiService.interpretSession( words: _session.words, question: _session.question ?? '', ); if (mounted) { final updated = _session.copyWith(aiInterpretation: result); setState(() { _session = updated; _isLoadingAi = false; }); await _repo.saveSession(updated); } } catch (e) { if (mounted) { setState(() => _isLoadingAi = false); ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text('Ошибка генерации: $e'), behavior: SnackBarBehavior.floating, ), ); } } } void _copySessionToClipboard() { final buf = StringBuffer(); buf.writeln('✨ Оракул 999 — Сессия Клеромантии ✨'); buf.writeln('Дата: ${_session.formattedDate}'); if (_session.question != null && _session.question!.isNotEmpty) { buf.writeln('Вопрос: «${_session.question}»'); } buf.writeln('Знаков в цепочке: ${_session.words.length}\n'); for (int i = 0; i < _session.words.length; i++) { final w = _session.words[i]; final pos = w.positionTitle != null ? ' (${w.positionTitle})' : ''; buf.writeln('🔮 Знак #${w.formattedSessionNumber}: ${w.word.toUpperCase()}$pos'); buf.writeln(' Аспект: ${w.partOfSpeech} • ${w.category}'); buf.writeln(' Смысл: ${w.symbolicMeaning}\n'); } if (_session.aiInterpretation != null) { buf.writeln('🤖 AI Трактовка Оракула (G4F):'); buf.writeln(_session.aiInterpretation); } Clipboard.setData(ClipboardData(text: buf.toString())); HapticFeedback.lightImpact(); ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: const Row( children: [ GradientStar(size: 18), SizedBox(width: 10), Expanded(child: Text('Вся сессия скопирована в буфер обмена')), ], ), duration: const Duration(seconds: 2), behavior: SnackBarBehavior.floating, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)), ), ); } @override Widget build(BuildContext context) { final theme = Theme.of(context); final isDark = theme.brightness == Brightness.dark; return Scaffold( appBar: AppBar( title: Row( children: [ const GradientStar(size: 22), const SizedBox(width: 8), Text( 'Знаки Сессии (${_session.words.length})', style: const TextStyle(fontWeight: FontWeight.w900), ), ], ), actions: [ IconButton( tooltip: 'Скопировать сессию', icon: const Icon(Icons.copy_rounded), onPressed: _copySessionToClipboard, ), ], ), body: SafeArea( child: SingleChildScrollView( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ // Question Banner if (_session.question != null && _session.question!.isNotEmpty) ...[ Container( padding: const EdgeInsets.all(12), decoration: BoxDecoration( color: const Color(0xFF1E2138), borderRadius: BorderRadius.circular(16), border: Border.all( color: const Color(0xFFFFD54F).withValues(alpha: 0.3), ), ), child: Row( children: [ const Icon(Icons.help_outline_rounded, size: 18, color: Color(0xFFFFD54F)), const SizedBox(width: 10), Expanded( child: Text( 'Вопрос: «${_session.question}»', style: const TextStyle( fontSize: 13, fontWeight: FontWeight.w600, color: Color(0xFFFFF9C4), fontStyle: FontStyle.italic, ), ), ), ], ), ), const SizedBox(height: 14), ], // AI Interpretation Box if generated or button if (_session.aiInterpretation != null) ...[ Container( padding: const EdgeInsets.all(16), decoration: BoxDecoration( gradient: const LinearGradient( begin: Alignment.topLeft, end: Alignment.bottomRight, colors: [Color(0xFF2A1E4A), Color(0xFF191833)], ), borderRadius: BorderRadius.circular(20), border: Border.all( color: const Color(0xFFBA68C8).withValues(alpha: 0.6), width: 1.2, ), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ const Row( children: [ Icon(Icons.psychology_rounded, size: 20, color: Color(0xFFE1BEE7)), SizedBox(width: 8), Text( 'AI ТРАКТОВКА ИСТОРИИ (G4F)', style: TextStyle( fontSize: 12, fontWeight: FontWeight.w900, letterSpacing: 0.8, color: Color(0xFFE1BEE7), ), ), ], ), IconButton( icon: const Icon(Icons.refresh_rounded, size: 18, color: Color(0xFFE1BEE7)), tooltip: 'Перегенерировать', onPressed: _fetchAiInterpretation, ), ], ), const SizedBox(height: 10), Text( _session.aiInterpretation!, style: const TextStyle( fontSize: 13.5, height: 1.5, color: Color(0xFFF3E5F5), ), ), ], ), ), const SizedBox(height: 16), ] else ...[ FilledButton.icon( onPressed: _isLoadingAi ? null : _fetchAiInterpretation, icon: _isLoadingAi ? const SizedBox( width: 18, height: 18, child: CircularProgressIndicator( strokeWidth: 2, valueColor: AlwaysStoppedAnimation(Color(0xFFFFD54F)), ), ) : const Icon(Icons.auto_awesome, size: 18, color: Color(0xFFE1BEE7)), label: Text( _isLoadingAi ? 'Синтез толкования...' : 'Синтезировать связную AI-трактовку (G4F)', style: const TextStyle( fontWeight: FontWeight.bold, fontSize: 13, color: Color(0xFFFFF9C4), ), ), style: FilledButton.styleFrom( backgroundColor: const Color(0xFF2A2145), padding: const EdgeInsets.symmetric(vertical: 14), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(16), side: const BorderSide( color: Color(0xFFBA68C8), width: 1.2, ), ), ), ), const SizedBox(height: 16), ], // Word Cards List ..._session.words.asMap().entries.map((entry) { final idx = entry.key; final w = entry.value; return Padding( padding: const EdgeInsets.only(bottom: 14), child: Card( elevation: 6, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(20), side: BorderSide( color: const Color(0xFFFFD54F).withValues(alpha: 0.25), ), ), color: isDark ? const Color(0xFF1B1D30) : theme.colorScheme.surface, child: Padding( padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Row( children: [ const GradientStar(size: 15), const SizedBox(width: 6), Text( '${idx + 1}. ЗНАК #${w.formattedSessionNumber}', style: const TextStyle( fontWeight: FontWeight.w900, fontSize: 13, color: Color(0xFFFFD54F), letterSpacing: 0.5, ), ), ], ), Container( padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 2), decoration: BoxDecoration( color: isDark ? const Color(0xFF262A48) : Colors.black12, borderRadius: BorderRadius.circular(8), ), child: Text( w.partOfSpeech, style: TextStyle( fontSize: 11, color: isDark ? const Color(0xFFB0B7DE) : Colors.black87, fontWeight: FontWeight.w600, ), ), ), ], ), const SizedBox(height: 10), Center( child: Text( w.word.toUpperCase(), style: const TextStyle( fontSize: 24, fontWeight: FontWeight.w900, letterSpacing: 1.5, color: Color(0xFFFFF9C4), ), ), ), const SizedBox(height: 10), Container( width: double.infinity, padding: const EdgeInsets.all(12), decoration: BoxDecoration( color: isDark ? const Color(0xFF131525) : theme.colorScheme.surfaceContainerLow, borderRadius: BorderRadius.circular(14), ), child: Text( w.symbolicMeaning, style: TextStyle( fontSize: 13, height: 1.45, color: isDark ? const Color(0xFFD4D6E6) : Colors.black87, ), ), ), ], ), ), ), ); }), ], ), ), ), ); } }