import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import '../models/history_entry_model.dart'; import '../models/word_model.dart'; import '../services/words_repository.dart'; import '../widgets/cleromancy_dialog.dart'; import '../widgets/d10_dice_roller_widget.dart'; import '../widgets/gradient_star_badge.dart'; import '../widgets/word_card_widget.dart'; class HomeSearchScreen extends StatefulWidget { const HomeSearchScreen({super.key}); @override State createState() => _HomeSearchScreenState(); } class _HomeSearchScreenState extends State { final _repo = WordsRepository(); final _questionController = TextEditingController(); final _diceRollerKey = GlobalKey(); WordItem? _currentWord; String? _activeHistoryId; bool _showKeypad = true; String _currentDigits = ''; // Tracks 0..3 digits input: e.g. "", "7", "74", "742" @override void dispose() { _questionController.dispose(); super.dispose(); } Future _setWord(WordItem word, {bool recordHistory = true}) async { final question = _questionController.text.trim(); String? newHistId; if (recordHistory) { newHistId = DateTime.now().millisecondsSinceEpoch.toString(); final entry = HistoryEntry( id: newHistId, timestamp: DateTime.now(), word: word.word, sessionNumber: word.sessionNumber, partOfSpeech: word.partOfSpeech, symbolicMeaning: word.description, readingType: 'Клеромантия (3× d10)', question: question.isNotEmpty ? question : null, ); await _repo.addHistoryEntry(entry); } setState(() { _currentWord = word; _activeHistoryId = newHistId ?? _activeHistoryId; _currentDigits = word.formattedSessionNumber; }); HapticFeedback.selectionClick(); } void _onKeypadTap(String val) { HapticFeedback.lightImpact(); if (val == 'C') { setState(() { _currentDigits = ''; }); return; } if (val == '⌫') { if (_currentDigits.isNotEmpty) { setState(() { _currentDigits = _currentDigits.substring(0, _currentDigits.length - 1); }); } return; } // Append digit up to 3 digits (1st d10, 2nd d10, 3rd d10) String newDigits; if (_currentDigits.length >= 3) { newDigits = val; } else { newDigits = _currentDigits + val; } setState(() { _currentDigits = newDigits; }); // Only resolve word when all 3 digits are provided! if (newDigits.length == 3) { final num = int.tryParse(newDigits); if (num != null && num <= 999) { final word = _repo.getWordBySessionNumber(num); if (word != null) { _setWord(word, recordHistory: true); } } } } void _onVirtualRollCompleted(int finalNumber) { final word = _repo.getWordBySessionNumber(finalNumber); if (word != null) { _setWord(word, recordHistory: true); } } void _resetToWelcome() { setState(() { _currentWord = null; _currentDigits = ''; _activeHistoryId = null; }); } void _goToNext() { if (_currentWord == null) return; final next = _repo.getNextWord(_currentWord!.sessionNumber); _setWord(next, recordHistory: false); } void _goToPrevious() { if (_currentWord == null) return; final prev = _repo.getPreviousWord(_currentWord!.sessionNumber); _setWord(prev, recordHistory: false); } void _reshuffleSession() { _repo.reshuffleSessionNumbers(); _resetToWelcome(); HapticFeedback.heavyImpact(); ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: const Row( children: [ GradientStar(size: 20), SizedBox(width: 10), Expanded( child: Text( 'Случайный порядок 1000 чисел перетасован заново!', style: TextStyle(fontWeight: FontWeight.w600), ), ), ], ), 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: const Row( children: [ GradientStar(size: 24), SizedBox(width: 10), Text( 'Оракул 999', style: TextStyle( fontSize: 20, fontWeight: FontWeight.w900, letterSpacing: 0.5, ), ), ], ), actions: [ IconButton( tooltip: 'Инструкция: Клеромантия и кубики d10', icon: const Icon(Icons.help_outline_rounded, color: Color(0xFFFFD54F)), onPressed: () => CleromancyGuideDialog.show(context), ), if (_currentWord != null) IconButton( tooltip: 'Новый вопрос / Сброс', icon: const Icon(Icons.refresh_rounded), onPressed: _resetToWelcome, ), IconButton( tooltip: 'Перетасовать матрицу (#000..#999)', icon: const Icon(Icons.shuffle_rounded), onPressed: _reshuffleSession, ), IconButton( tooltip: _showKeypad ? 'Скрыть панель' : 'Показать панель', icon: Icon(_showKeypad ? Icons.dialpad_outlined : Icons.dialpad), onPressed: () { setState(() => _showKeypad = !_showKeypad); }, ), ], ), body: SafeArea( child: SingleChildScrollView( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10), child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ // Question Input Field TextField( controller: _questionController, decoration: InputDecoration( labelText: 'Ваш вопрос или намерение (необязательно)', hintText: 'Например: В чем корень текущей ситуации?', prefixIcon: const Icon(Icons.help_outline_rounded, color: Color(0xFFFFD54F), size: 20), suffixIcon: _questionController.text.isNotEmpty ? IconButton( icon: const Icon(Icons.clear, size: 18), onPressed: () => _questionController.clear(), ) : null, filled: true, fillColor: isDark ? const Color(0xFF17192C) : theme.colorScheme.surfaceContainerHigh, border: OutlineInputBorder( borderRadius: BorderRadius.circular(16), borderSide: BorderSide( color: const Color(0xFFFFD54F).withValues(alpha: 0.25), ), ), enabledBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(16), borderSide: BorderSide( color: const Color(0xFFFFD54F).withValues(alpha: 0.2), ), ), focusedBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(16), borderSide: const BorderSide( color: Color(0xFFFFD54F), width: 1.5, ), ), ), ), const SizedBox(height: 12), // D10 Dice Roller Slots Widget (Clean & without prefilled junk) D10DiceRollerWidget( key: _diceRollerKey, digits: _currentDigits, isRolling: false, onRollPressed: () {}, onRollCompleted: _onVirtualRollCompleted, ), const SizedBox(height: 14), // Welcome Idle State OR Active Word Card if (_currentWord == null) ...[ // Welcome Initiation Card Container( padding: const EdgeInsets.all(20), decoration: BoxDecoration( gradient: LinearGradient( begin: Alignment.topLeft, end: Alignment.bottomRight, colors: [ const Color(0xFF1F223B), const Color(0xFF131526), ], ), borderRadius: BorderRadius.circular(24), border: Border.all( color: const Color(0xFFFFD54F).withValues(alpha: 0.35), width: 1.2, ), ), child: Column( children: [ const GradientStar(size: 38), const SizedBox(height: 12), const Text( 'СВЯЩЕННЫЙ ЖРЕБИЙ КЛЕРОМАНТИИ', textAlign: TextAlign.center, style: TextStyle( fontSize: 15, fontWeight: FontWeight.w900, letterSpacing: 0.8, color: Color(0xFFFFF9C4), ), ), const SizedBox(height: 8), Text( 'Сформулируйте вопрос, затем совершите 3 броска кубика d10 кнопкой выше или наберите 3 выпавших грани на панели.', textAlign: TextAlign.center, style: TextStyle( fontSize: 13, height: 1.4, color: theme.colorScheme.onSurface.withValues(alpha: 0.85), ), ), const SizedBox(height: 14), OutlinedButton.icon( onPressed: () => CleromancyGuideDialog.show(context), icon: const Icon(Icons.menu_book_rounded, size: 16, color: Color(0xFFFFD54F)), label: const Text( 'Инструкция по броскам d10', style: TextStyle( color: Color(0xFFFFD54F), fontWeight: FontWeight.bold, fontSize: 12.5, ), ), style: OutlinedButton.styleFrom( side: const BorderSide(color: Color(0xFFFFD54F), width: 1), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(14), ), ), ), ], ), ), ] else ...[ // Main Sacred Word Card Display AnimatedSwitcher( duration: const Duration(milliseconds: 300), transitionBuilder: (child, animation) { return FadeTransition( opacity: animation, child: SlideTransition( position: Tween( begin: const Offset(0.0, 0.04), end: Offset.zero, ).animate(animation), child: child, ), ); }, child: WordCardWidget( key: ValueKey('${_currentWord!.id}_${_currentWord!.sessionNumber}'), word: _currentWord!, question: _questionController.text.trim(), historyEntryId: _activeHistoryId, onNext: _goToNext, onPrevious: _goToPrevious, onRandom: () { _diceRollerKey.currentState?.triggerRollAnimation(); }, ), ), ], const SizedBox(height: 14), // Interactive Numeric Keypad (Directly maps to 3 d10 dice slots) if (_showKeypad) ...[ Container( padding: const EdgeInsets.all(12), decoration: BoxDecoration( color: isDark ? const Color(0xFF17192A) : theme.colorScheme.surfaceContainerLow, borderRadius: BorderRadius.circular(20), border: Border.all( color: const Color(0xFFFFD54F).withValues(alpha: 0.25), ), ), child: Column( children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ const Row( children: [ Icon(Icons.casino_outlined, size: 15, color: Color(0xFFFFD54F)), SizedBox(width: 6), Text( 'Ввод граней d10:', style: TextStyle( fontSize: 12, fontWeight: FontWeight.w700, color: Color(0xFFFFD54F), ), ), ], ), Text( _currentDigits.isEmpty ? 'Ожидание 3 цифр' : (_currentDigits.length == 3 ? 'Код: #$_currentDigits' : 'Введено: ${_currentDigits.length} из 3'), style: TextStyle( fontSize: 11, fontWeight: FontWeight.bold, color: _currentDigits.length == 3 ? const Color(0xFFFFD54F) : theme.colorScheme.outline, ), ), ], ), const SizedBox(height: 10), _buildKeypadRow(['1', '2', '3']), const SizedBox(height: 8), _buildKeypadRow(['4', '5', '6']), const SizedBox(height: 8), _buildKeypadRow(['7', '8', '9']), const SizedBox(height: 8), _buildKeypadRow(['C', '0', '⌫']), ], ), ), const SizedBox(height: 16), ], ], ), ), ), ); } Widget _buildKeypadRow(List keys) { return Row( children: keys.map((key) { final isSpecial = key == 'C' || key == '⌫'; final theme = Theme.of(context); final isDark = theme.brightness == Brightness.dark; return Expanded( child: Padding( padding: const EdgeInsets.symmetric(horizontal: 4), child: Material( color: isSpecial ? const Color(0xFF2A2D4A) : isDark ? const Color(0xFF20233A) : theme.colorScheme.surface, borderRadius: BorderRadius.circular(14), elevation: 1, child: InkWell( onTap: () => _onKeypadTap(key), borderRadius: BorderRadius.circular(14), child: Container( height: 46, alignment: Alignment.center, decoration: BoxDecoration( borderRadius: BorderRadius.circular(14), border: Border.all( color: isSpecial ? const Color(0xFFFFD54F).withValues(alpha: 0.4) : Colors.white10, ), ), child: Text( key, style: TextStyle( fontSize: 20, fontWeight: FontWeight.bold, color: isSpecial ? const Color(0xFFFFF9C4) : isDark ? Colors.white : Colors.black87, ), ), ), ), ), ), ); }).toList(), ); } }