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 'session_result_screen.dart'; class HomeSearchScreen extends StatefulWidget { const HomeSearchScreen({super.key}); @override State createState() => _HomeSearchScreenState(); } class _HomeSearchScreenState extends State { final _repo = WordsRepository(); final _questionController = TextEditingController(); final _countController = TextEditingController(text: '1'); final _diceRollerKey = GlobalKey(); int _wordsCount = 1; // 1 to 9 words in the session int _activeWordIndex = 0; // 0.._wordsCount-1 List _wordsDigits = ['']; // 3-digit strings for each word bool _showKeypad = true; @override void initState() { super.initState(); _countController.addListener(_onCountChanged); } @override void dispose() { _countController.removeListener(_onCountChanged); _countController.dispose(); _questionController.dispose(); super.dispose(); } void _onCountChanged() { final text = _countController.text.trim(); final count = int.tryParse(text); if (count != null && count >= 1 && count <= 9) { if (count != _wordsCount) { setState(() { _wordsCount = count; _adjustDigitsList(); }); } } } void _adjustDigitsList() { final current = List.from(_wordsDigits); if (current.length < _wordsCount) { while (current.length < _wordsCount) { current.add(''); } } else if (current.length > _wordsCount) { current.removeRange(_wordsCount, current.length); } _wordsDigits = current; if (_activeWordIndex >= _wordsCount) { _activeWordIndex = _wordsCount - 1; } } void _onKeypadTap(String val) { HapticFeedback.lightImpact(); if (val == 'C') { setState(() { _wordsDigits[_activeWordIndex] = ''; }); return; } if (val == '⌫') { final current = _wordsDigits[_activeWordIndex]; if (current.isNotEmpty) { setState(() { _wordsDigits[_activeWordIndex] = current.substring(0, current.length - 1); }); } else if (_activeWordIndex > 0) { setState(() { _activeWordIndex--; }); } return; } // Append digit to current active word (up to 3 digits) final current = _wordsDigits[_activeWordIndex]; String newDigits; if (current.length >= 3) { newDigits = val; } else { newDigits = current + val; } setState(() { _wordsDigits[_activeWordIndex] = newDigits; }); // If 3 digits filled and more words remain, auto-advance to next word! if (newDigits.length == 3 && _activeWordIndex < _wordsCount - 1) { Future.delayed(const Duration(milliseconds: 150), () { if (mounted) { setState(() { _activeWordIndex++; }); } }); } } void _onVirtualRollCompleted(int finalNumber) { final formatted = finalNumber.toString().padLeft(3, '0'); setState(() { _wordsDigits[_activeWordIndex] = formatted; }); // Advance to next word if not last if (_activeWordIndex < _wordsCount - 1) { Future.delayed(const Duration(milliseconds: 200), () { if (mounted) { setState(() { _activeWordIndex++; }); } }); } } bool get _isSessionReady { if (_wordsDigits.length != _wordsCount) return false; return _wordsDigits.every((d) => d.length == 3); } void _openSessionResults() { final sessionWords = []; for (int i = 0; i < _wordsCount; i++) { final digits = _wordsDigits[i]; final num = int.tryParse(digits) ?? 0; final wordItem = _repo.getWordBySessionNumber(num) ?? WordItem( id: num, word: 'Символ #$digits', partOfSpeech: 'знак', frequency: 0, category: 'Символ', description: 'Сакральный знак под номером $digits', ); sessionWords.add(SessionWord.fromWordItem(wordItem)); } final question = _questionController.text.trim(); final session = OracleSession( id: DateTime.now().millisecondsSinceEpoch.toString(), timestamp: DateTime.now(), question: question.isNotEmpty ? question : null, wordsCount: _wordsCount, words: sessionWords, ); Navigator.push( context, MaterialPageRoute( builder: (_) => SessionResultScreen(session: session), ), ); } void _resetSession() { setState(() { _activeWordIndex = 0; _wordsDigits = List.filled(_wordsCount, ''); }); } void _reshuffleMatrix() { _repo.reshuffleSessionNumbers(); _resetSession(); 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; final currentActiveDigits = _activeWordIndex < _wordsDigits.length ? _wordsDigits[_activeWordIndex] : ''; 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), ), IconButton( tooltip: 'Очистить броски', icon: const Icon(Icons.refresh_rounded), onPressed: _resetSession, ), IconButton( tooltip: 'Перетасовать матрицу (#000..#999)', icon: const Icon(Icons.shuffle_rounded), onPressed: _reshuffleMatrix, ), 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: [ // Row: Question & Words count selector (1..9) Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ // Question Input Expanded( child: 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(width: 10), // Words Count Input Box (1..9) Container( width: 78, height: 56, decoration: BoxDecoration( color: isDark ? const Color(0xFF17192C) : theme.colorScheme.surfaceContainerHigh, borderRadius: BorderRadius.circular(16), border: Border.all( color: const Color(0xFFFFD54F).withValues(alpha: 0.4), ), ), child: TextField( controller: _countController, keyboardType: TextInputType.number, textAlign: TextAlign.center, maxLength: 1, style: const TextStyle( fontSize: 20, fontWeight: FontWeight.bold, color: Color(0xFFFFF9C4), ), decoration: const InputDecoration( counterText: '', labelText: 'Слов', labelStyle: TextStyle(fontSize: 11, color: Color(0xFFFFD54F)), border: InputBorder.none, contentPadding: EdgeInsets.symmetric(vertical: 6, horizontal: 8), ), ), ), ], ), const SizedBox(height: 12), // Multi-Word Slots Progress Indicator (if > 1 word) if (_wordsCount > 1) ...[ Container( padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 8), decoration: BoxDecoration( color: isDark ? const Color(0xFF151829) : theme.colorScheme.surfaceContainerLow, borderRadius: BorderRadius.circular(16), border: Border.all( color: const Color(0xFFFFD54F).withValues(alpha: 0.2), ), ), child: SingleChildScrollView( scrollDirection: Axis.horizontal, child: Row( children: List.generate(_wordsCount, (i) { final isSelected = i == _activeWordIndex; final digits = i < _wordsDigits.length ? _wordsDigits[i] : ''; final isFilled = digits.length == 3; return Padding( padding: const EdgeInsets.only(right: 6), child: InkWell( onTap: () { setState(() => _activeWordIndex = i); HapticFeedback.selectionClick(); }, borderRadius: BorderRadius.circular(12), child: Container( padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 6), decoration: BoxDecoration( color: isSelected ? const Color(0xFF2A2D4A) : (isFilled ? const Color(0xFF1E2138) : Colors.transparent), borderRadius: BorderRadius.circular(12), border: Border.all( color: isSelected ? const Color(0xFFFFD54F) : (isFilled ? const Color(0xFFFFD54F).withValues(alpha: 0.4) : Colors.white12), width: isSelected ? 1.5 : 1.0, ), ), child: Row( children: [ Text( 'Слово ${i + 1}: ', style: TextStyle( fontSize: 11, fontWeight: isSelected ? FontWeight.bold : FontWeight.normal, color: isSelected ? const Color(0xFFFFF9C4) : theme.colorScheme.outline, ), ), Text( isFilled ? '#$digits' : (digits.isEmpty ? '• • •' : '$digits..'), style: TextStyle( fontSize: 12, fontWeight: FontWeight.w900, color: isFilled ? const Color(0xFFFFD54F) : Colors.white54, ), ), ], ), ), ), ); }), ), ), ), const SizedBox(height: 10), ], // D10 Dice Roller Slots Widget (Purely for rolling/entering faces before opening word) D10DiceRollerWidget( key: _diceRollerKey, digits: currentActiveDigits, isRolling: false, onRollPressed: () {}, onRollCompleted: _onVirtualRollCompleted, ), const SizedBox(height: 14), // Button to open the Result Screen when ready SizedBox( width: double.infinity, child: FilledButton.icon( onPressed: _isSessionReady ? _openSessionResults : null, icon: const Icon(Icons.visibility_rounded, size: 20), label: Text( _isSessionReady ? '🔮 ОТКРЫТЬ ЗНАКИ И ТРАКТОВКУ ($_wordsCount ${_wordsCount == 1 ? "знак" : (_wordsCount < 5 ? "знака" : "знаков")})' : 'Заполните броски (Слово ${_activeWordIndex + 1} из $_wordsCount)', style: const TextStyle( fontWeight: FontWeight.w900, letterSpacing: 0.6, fontSize: 13.5, ), ), style: FilledButton.styleFrom( backgroundColor: const Color(0xFF2A2D4A), foregroundColor: const Color(0xFFFFF9C4), padding: const EdgeInsets.symmetric(vertical: 16), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(18), side: BorderSide( color: _isSessionReady ? const Color(0xFFFFD54F) : const Color(0xFFFFD54F).withValues(alpha: 0.3), width: 1.5, ), ), ), ), ), const SizedBox(height: 14), // Interactive Numeric Keypad (Directly inputs to active d10 word 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: [ Row( children: [ const Icon(Icons.casino_outlined, size: 15, color: Color(0xFFFFD54F)), const SizedBox(width: 6), Text( 'Ввод граней (Слово ${_activeWordIndex + 1} из $_wordsCount):', style: const TextStyle( fontSize: 12, fontWeight: FontWeight.w700, color: Color(0xFFFFD54F), ), ), ], ), Text( currentActiveDigits.length == 3 ? 'Код: #$currentActiveDigits' : 'Введено: ${currentActiveDigits.length} из 3', style: TextStyle( fontSize: 11, fontWeight: FontWeight.bold, color: currentActiveDigits.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(), ); } }