import 'package:flutter/material.dart'; import 'package:hive_flutter/hive_flutter.dart'; import 'package:lucide_icons/lucide_icons.dart'; import 'package:go_router/go_router.dart'; import 'package:intl/intl.dart'; import '../../../app/theme/app_colors.dart'; import '../../../core/widgets/arabic_text.dart'; import '../../../core/widgets/bottom_sheet_content_padding.dart'; import '../../../data/local/hive_boxes.dart'; import '../../../data/local/models/quran_bookmark.dart'; import '../../../data/local/models/app_settings.dart'; import '../../../data/services/muslim_api_service.dart'; class QuranBookmarksScreen extends StatefulWidget { final bool isSimpleModeTab; const QuranBookmarksScreen({ super.key, this.isSimpleModeTab = false, }); @override State createState() => _QuranBookmarksScreenState(); } class _QuranBookmarksScreenState extends State { bool _showLatin = true; bool _showTerjemahan = true; final Map?>> _surahFutureCache = {}; final Map> _bookmarkFutureCache = {}; String _readingRoute(int surahId, int verseId) { final isSimple = Hive.box(HiveBoxes.settings).get('default')?.simpleMode ?? false; final base = isSimple ? '/quran' : '/tools/quran'; return '$base/$surahId?startVerse=$verseId'; } @override void initState() { super.initState(); final box = Hive.box(HiveBoxes.settings); final settings = box.get('default') ?? AppSettings(); _showLatin = settings.showLatin; _showTerjemahan = settings.showTerjemahan; } void _showDisplaySettings() { showModalBottomSheet( context: context, isScrollControlled: true, useSafeArea: true, shape: const RoundedRectangleBorder( borderRadius: BorderRadius.vertical(top: Radius.circular(20)), ), builder: (ctx) => StatefulBuilder( builder: (context, setModalState) { return Padding( padding: bottomSheetContentPadding(context), child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text( 'Pengaturan Tampilan', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold), ), const SizedBox(height: 16), SwitchListTile( title: const Text('Tampilkan Latin'), value: _showLatin, activeColor: AppColors.primary, onChanged: (val) { setModalState(() => _showLatin = val); setState(() => _showLatin = val); final box = Hive.box(HiveBoxes.settings); final settings = box.get('default') ?? AppSettings(); settings.showLatin = val; settings.save(); }, ), SwitchListTile( title: const Text('Tampilkan Terjemahan'), value: _showTerjemahan, activeColor: AppColors.primary, onChanged: (val) { setModalState(() => _showTerjemahan = val); setState(() => _showTerjemahan = val); final box = Hive.box(HiveBoxes.settings); final settings = box.get('default') ?? AppSettings(); settings.showTerjemahan = val; settings.save(); }, ), const SizedBox(height: 16), ], ), ); }, ), ); } Future?> _getSurah(int surahId) { return _surahFutureCache.putIfAbsent( surahId, () => MuslimApiService.instance.getSurah(surahId), ); } Future<_ResolvedBookmarkContent?> _loadResolvedBookmarkContent( QuranBookmark bookmark, ) async { final surah = await _getSurah(bookmark.surahId); final verses = List>.from(surah?['ayat'] ?? []); final verseIndex = bookmark.verseId - 1; if (verseIndex < 0 || verseIndex >= verses.length) return null; final verse = verses[verseIndex]; final resolved = _ResolvedBookmarkContent( verseText: verse['teksArab']?.toString().trim().isNotEmpty == true ? verse['teksArab'].toString().trim() : bookmark.verseText, verseLatin: verse['teksLatin']?.toString().trim().isNotEmpty == true ? verse['teksLatin'].toString().trim() : bookmark.verseLatin, verseTranslation: verse['teksIndonesia']?.toString().trim().isNotEmpty == true ? verse['teksIndonesia'].toString().trim() : bookmark.verseTranslation, ); final needsUpdate = bookmark.verseText != resolved.verseText || bookmark.verseLatin != resolved.verseLatin || bookmark.verseTranslation != resolved.verseTranslation; if (needsUpdate) { bookmark.verseText = resolved.verseText; bookmark.verseLatin = resolved.verseLatin; bookmark.verseTranslation = resolved.verseTranslation; await bookmark.save(); } return resolved; } Future<_ResolvedBookmarkContent?> _getResolvedBookmarkContent( QuranBookmark bookmark, ) { final bookmarkKey = bookmark.key ?? '${bookmark.surahId}_${bookmark.verseId}'; return _bookmarkFutureCache.putIfAbsent( bookmarkKey, () => _loadResolvedBookmarkContent(bookmark), ); } @override Widget build(BuildContext context) { final isDark = Theme.of(context).brightness == Brightness.dark; return Scaffold( appBar: AppBar( title: const Text('Markah Al-Quran'), centerTitle: false, actions: [ IconButton( icon: const Icon(LucideIcons.settings2), onPressed: _showDisplaySettings, ), ], ), body: SafeArea( top: false, bottom: !widget.isSimpleModeTab, child: ValueListenableBuilder( valueListenable: Hive.box(HiveBoxes.bookmarks).listenable(), builder: (context, Box box, _) { if (box.isEmpty) { return Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon( LucideIcons.bookmark, size: 64, color: AppColors.primary.withValues(alpha: 0.3), ), const SizedBox(height: 16), Text( 'Belum ada markah', style: TextStyle( fontSize: 18, fontWeight: FontWeight.w600, color: isDark ? Colors.white : Colors.black87, ), ), const SizedBox(height: 8), Text( 'Tandai ayat saat membaca Al-Quran', style: TextStyle( fontSize: 14, color: isDark ? AppColors.textSecondaryDark : AppColors.textSecondaryLight, ), textAlign: TextAlign.center, ), ], ), ); } // Filter bookmarks final allBookmarks = box.values.toList(); final lastRead = allBookmarks.where((b) => b.isLastRead).toList(); final favorites = allBookmarks.where((b) => !b.isLastRead).toList() ..sort((a, b) => b.savedAt.compareTo(a.savedAt)); return ListView( padding: const EdgeInsets.all(16), children: [ if (lastRead.isNotEmpty) ...[ const Text( 'TERAKHIR DIBACA', style: TextStyle( fontSize: 11, fontWeight: FontWeight.w700, letterSpacing: 1.5, color: AppColors.sage, ), ), const SizedBox(height: 12), _buildBookmarkCard(context, lastRead.first, isDark, box, isLastRead: true), const SizedBox(height: 24), ], if (favorites.isNotEmpty) ...[ const Text( 'AYAT FAVORIT', style: TextStyle( fontSize: 11, fontWeight: FontWeight.w700, letterSpacing: 1.5, color: AppColors.sage, ), ), const SizedBox(height: 12), ...favorites.map((fav) => Padding( padding: const EdgeInsets.only(bottom: 12), child: _buildBookmarkCard(context, fav, isDark, box, isLastRead: false), )), ], ], ); }, ), ), ); } Widget _buildBookmarkCard(BuildContext context, QuranBookmark bookmark, bool isDark, Box box, {required bool isLastRead}) { final dateStr = DateFormat('dd MMM yyyy, HH:mm').format(bookmark.savedAt); final resolvedFuture = _getResolvedBookmarkContent(bookmark); return InkWell( onTap: () => context.push(_readingRoute(bookmark.surahId, bookmark.verseId)), borderRadius: BorderRadius.circular(16), child: Container( padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: isDark ? AppColors.surfaceDark : AppColors.surfaceLight, borderRadius: BorderRadius.circular(16), border: Border.all( color: isLastRead ? AppColors.primary.withValues(alpha: 0.3) : (isDark ? AppColors.primary.withValues(alpha: 0.1) : AppColors.cream), width: isLastRead ? 1.5 : 1.0, ), boxShadow: isLastRead ? [ BoxShadow( color: AppColors.primary.withValues(alpha: 0.05), blurRadius: 10, offset: const Offset(0, 4), ) ] : null, ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Container( padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 4), decoration: BoxDecoration( color: AppColors.primary.withValues(alpha: 0.1), borderRadius: BorderRadius.circular(8), ), child: Row( mainAxisSize: MainAxisSize.min, children: [ if (isLastRead) ...[ const Icon(LucideIcons.pin, size: 12, color: AppColors.primary), const SizedBox(width: 4), ], Text( 'QS. ${bookmark.surahName}: ${bookmark.verseId}', style: const TextStyle( fontSize: 12, fontWeight: FontWeight.w700, color: AppColors.primary, ), ), ], ), ), IconButton( icon: const Icon(LucideIcons.trash2, color: Colors.red, size: 20), onPressed: () => box.delete(bookmark.key), padding: EdgeInsets.zero, constraints: const BoxConstraints(), ), ], ), const SizedBox(height: 16), FutureBuilder<_ResolvedBookmarkContent?>( future: resolvedFuture, builder: (context, snapshot) { final content = snapshot.data ?? _ResolvedBookmarkContent( verseText: bookmark.verseText, verseLatin: bookmark.verseLatin, verseTranslation: bookmark.verseTranslation, ); return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Align( alignment: Alignment.centerRight, child: ArabicText( content.verseText, textAlign: TextAlign.right, baseFontSize: 22, fontWeight: FontWeight.w400, height: 1.8, ), ), if (_showLatin && content.verseLatin != null) ...[ const SizedBox(height: 12), Text( content.verseLatin!, style: const TextStyle( fontSize: 13, fontStyle: FontStyle.italic, color: AppColors.primary, ), ), ], if (_showTerjemahan && content.verseTranslation != null) ...[ const SizedBox(height: 8), Text( content.verseTranslation!, style: TextStyle( fontSize: 14, height: 1.6, color: isDark ? AppColors.textSecondaryDark : AppColors.textSecondaryLight, ), ), ], ], ); }, ), const SizedBox(height: 16), if (isLastRead) ...[ SizedBox( width: double.infinity, child: FilledButton.icon( onPressed: () => context .push(_readingRoute(bookmark.surahId, bookmark.verseId)), icon: const Icon(LucideIcons.bookOpen, size: 18), label: const Text('Lanjutkan Membaca'), style: FilledButton.styleFrom( padding: const EdgeInsets.symmetric(vertical: 12), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(10)), ), ), ), const SizedBox(height: 12), ], Row( children: [ Icon( LucideIcons.clock, size: 12, color: isDark ? AppColors.textSecondaryDark : AppColors.textSecondaryLight, ), const SizedBox(width: 4), Text( '${isLastRead ? 'Ditandai' : 'Disimpan'}: $dateStr', style: TextStyle( fontSize: 10, color: isDark ? AppColors.textSecondaryDark : AppColors.textSecondaryLight, ), ), ], ), ], ), ), ); } } class _ResolvedBookmarkContent { const _ResolvedBookmarkContent({ required this.verseText, this.verseLatin, this.verseTranslation, }); final String verseText; final String? verseLatin; final String? verseTranslation; }