import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:shared_preferences/shared_preferences.dart'; class AIStatsScreen extends ConsumerStatefulWidget { const AIStatsScreen({super.key}); @override ConsumerState createState() => _AIStatsScreenState(); } class _AIStatsScreenState extends ConsumerState { int _totalRequests = 0; int _totalTokens = 0; int _mockRequests = 0; int _realRequests = 0; Map _requestsByType = {}; bool _isLoading = true; @override void initState() { super.initState(); _loadStats(); } Future _loadStats() async { try { final prefs = await SharedPreferences.getInstance(); setState(() { _totalRequests = prefs.getInt('ai_total_requests') ?? 0; _totalTokens = prefs.getInt('ai_total_tokens') ?? 0; _mockRequests = prefs.getInt('ai_mock_requests') ?? 0; _realRequests = prefs.getInt('ai_real_requests') ?? 0; _requestsByType = { 'Генерация подзадач': prefs.getInt('ai_subtasks') ?? 0, 'Приоритизация': prefs.getInt('ai_priority') ?? 0, 'Описания': prefs.getInt('ai_descriptions') ?? 0, 'Mind-карты': prefs.getInt('ai_mindmaps') ?? 0, 'Планирование': prefs.getInt('ai_scheduling') ?? 0, }; _isLoading = false; }); } catch (e) { setState(() => _isLoading = false); } } Future _resetStats() async { final confirmed = await showDialog( context: context, builder: (context) => AlertDialog( title: const Text('Сбросить статистику?'), content: const Text('Все данные об использовании AI будут удалены'), actions: [ TextButton( onPressed: () => Navigator.pop(context, false), child: const Text('Отмена'), ), TextButton( onPressed: () => Navigator.pop(context, true), style: TextButton.styleFrom(foregroundColor: Colors.red), child: const Text('Сбросить'), ), ], ), ); if (confirmed == true) { final prefs = await SharedPreferences.getInstance(); await prefs.remove('ai_total_requests'); await prefs.remove('ai_total_tokens'); await prefs.remove('ai_mock_requests'); await prefs.remove('ai_real_requests'); await prefs.remove('ai_subtasks'); await prefs.remove('ai_priority'); await prefs.remove('ai_descriptions'); await prefs.remove('ai_mindmaps'); await prefs.remove('ai_scheduling'); await _loadStats(); } } @override Widget build(BuildContext context) { if (_isLoading) { return const Scaffold( body: Center(child: CircularProgressIndicator()), ); } return Scaffold( appBar: AppBar( title: const Text('AI Статистика'), actions: [ IconButton( icon: const Icon(Icons.refresh), onPressed: _loadStats, tooltip: 'Обновить', ), IconButton( icon: const Icon(Icons.delete_sweep), onPressed: _resetStats, tooltip: 'Сбросить', ), ], ), body: ListView( padding: const EdgeInsets.all(16), children: [ // Общая статистика _buildStatCard( 'Общая статистика', [ _buildBigStat('Всего запросов', _totalRequests.toString()), const Divider(), _buildStatRow('Mock запросов', _mockRequests.toString()), _buildStatRow('Реальных запросов', _realRequests.toString()), _buildStatRow('Использовано токенов', _totalTokens.toString()), ], ), const SizedBox(height: 24), // Запросы по типам _buildStatCard( 'Запросы по типам', _requestsByType.entries .map((e) => _buildStatRow(e.key, e.value.toString())) .toList(), ), const SizedBox(height: 24), // График использования (простой) _buildStatCard( 'Использование', [ SizedBox( height: 150, child: Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, crossAxisAlignment: CrossAxisAlignment.end, children: _requestsByType.entries.map((entry) { final max = _requestsByType.values.fold( 1, (prev, element) => prev > element ? prev : element); final height = (entry.value / max) * 100; return Column( children: [ Text(entry.value.toString()), const SizedBox(height: 4), Container( width: 30, height: height, decoration: BoxDecoration( gradient: const LinearGradient( begin: Alignment.topCenter, end: Alignment.bottomCenter, colors: [Colors.blue, Colors.blueAccent], ), borderRadius: BorderRadius.circular(4), ), ), const SizedBox(height: 8), SizedBox( width: 60, child: Text( entry.key.split(' ')[0], textAlign: TextAlign.center, style: const TextStyle(fontSize: 10), overflow: TextOverflow.ellipsis, ), ), ], ); }).toList(), ), ), ], ), const SizedBox(height: 24), // Информация _buildInfoCard(), ], ), ); } Widget _buildStatCard(String title, List children) { return Container( padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: Theme.of(context).cardColor, borderRadius: BorderRadius.circular(12), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.05), blurRadius: 8, offset: const Offset(0, 2), ), ], ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( title, style: Theme.of(context).textTheme.titleMedium?.copyWith( fontWeight: FontWeight.bold, ), ), const SizedBox(height: 16), ...children, ], ), ); } Widget _buildBigStat(String label, String value) { return Column( children: [ Text( value, style: const TextStyle( fontSize: 36, fontWeight: FontWeight.bold, color: Colors.blue, ), ), const SizedBox(height: 4), Text(label, style: TextStyle(color: Colors.grey[600])), ], ); } Widget _buildStatRow(String label, String value) { return Padding( padding: const EdgeInsets.symmetric(vertical: 4), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text(label, style: TextStyle(color: Colors.grey[600])), Text( value, style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 16), ), ], ), ); } Widget _buildInfoCard() { return Container( padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: Colors.blue.withOpacity(0.1), borderRadius: BorderRadius.circular(12), border: Border.all(color: Colors.blue.withOpacity(0.3)), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ const Icon(Icons.info_outline, color: Colors.blue), const SizedBox(width: 8), Text( 'Информация', style: Theme.of(context).textTheme.titleMedium?.copyWith( fontWeight: FontWeight.bold, color: Colors.blue, ), ), ], ), const SizedBox(height: 12), const Text( '• Сейчас работает MOCK режим\n' '• Реальные запросы к DeepSeek отключены\n' '• Токены не расходуются\n\n' 'Для включения реального AI:\n' '1. Пополните баланс DeepSeek\n' '2. Установите useMockMode = false\n' '3. Перезапустите приложение', style: TextStyle(fontSize: 13), ), ], ), ); } }