import 'dart:async';

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart';
import 'package:hive_flutter/hive_flutter.dart';
import 'package:intl/intl.dart';
import 'package:lucide_icons/lucide_icons.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/app_settings.dart';
import '../../../data/local/models/daily_worship_log.dart';
import '../../../data/local/models/dzikir_counter.dart';
import '../../../data/local/models/dzikir_log.dart';
import '../../../data/local/models/shalat_log.dart';
import '../../../data/services/muslim_api_service.dart';

class DzikirScreen extends ConsumerStatefulWidget {
  final bool isSimpleModeTab;
  const DzikirScreen({super.key, this.isSimpleModeTab = false});

  @override
  ConsumerState<DzikirScreen> createState() => _DzikirScreenState();
}

class _DzikirScreenState extends ConsumerState<DzikirScreen>
    with SingleTickerProviderStateMixin, WidgetsBindingObserver {
  static const String _quranBismillah =
      'بِسْمِ اللّٰهِ الرَّحْمٰنِ الرَّحِيْمِ';
  late TabController _tabController;

  final Map<String, PageController> _pageControllers = {
    'pagi': PageController(),
    'petang': PageController(),
    'harian': PageController(),
  };

  final Map<String, int> _focusPageIndex = {
    'pagi': 0,
    'petang': 0,
    'harian': 0,
  };

  List<Map<String, dynamic>> _pagiItems = [];
  List<Map<String, dynamic>> _petangItems = [];
  List<Map<String, dynamic>> _harianItems = [];
  Map<String, dynamic>? _pagiIntroItem;
  Map<String, dynamic>? _petangIntroItem;
  bool _loading = true;
  String? _error;

  late Box<DzikirCounter> _counterBox;
  late String _todayKey;
  Timer? _dayResetTimer;

  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addObserver(this);
    _tabController = TabController(length: 3, vsync: this);
    _tabController.addListener(() {
      if (!mounted) return;
      setState(() {});
    });
    _counterBox = Hive.box<DzikirCounter>(HiveBoxes.dzikirCounters);
    _todayKey = _currentTodayKey();
    _scheduleDayResetTimer();
    _loadData();
  }

  @override
  void dispose() {
    WidgetsBinding.instance.removeObserver(this);
    _dayResetTimer?.cancel();
    _tabController.dispose();
    for (final controller in _pageControllers.values) {
      controller.dispose();
    }
    super.dispose();
  }

  @override
  void didChangeAppLifecycleState(AppLifecycleState state) {
    if (state == AppLifecycleState.resumed) {
      _refreshTodayScope();
      _scheduleDayResetTimer();
    }
  }

  String _currentTodayKey() => DateFormat('yyyy-MM-dd').format(DateTime.now());

  void _scheduleDayResetTimer() {
    _dayResetTimer?.cancel();
    final now = DateTime.now();
    final nextMidnight = DateTime(now.year, now.month, now.day + 1);
    final delay = nextMidnight.difference(now) + const Duration(seconds: 1);
    _dayResetTimer = Timer(delay, () {
      _refreshTodayScope();
      _scheduleDayResetTimer();
    });
  }

  void _refreshTodayScope() {
    final nextTodayKey = _currentTodayKey();
    if (nextTodayKey == _todayKey) return;

    _todayKey = nextTodayKey;
    if (_harianItems.isNotEmpty) {
      _seedHarianProgressFromLinkedDzikir();
    }
    if (!mounted) return;
    setState(() {});
  }

  String _counterScopeKeyForPrefix(String prefix) {
    return _todayKey;
  }

  String _counterDateKeyForPrefix(String prefix) {
    return _todayKey;
  }

  Future<void> _loadData() async {
    _refreshTodayScope();
    setState(() {
      _loading = true;
      _error = null;
    });

    try {
      final pagi = await MuslimApiService.instance.getDzikirByType(
        'pagi',
        strict: true,
      );
      final petang = await MuslimApiService.instance.getDzikirByType(
        'petang',
        strict: true,
      );

      if (!mounted) return;
      final pagiNormalized = _normalizeRumayshoDzikir('pagi', pagi);
      final petangNormalized = _normalizeRumayshoDzikir('petang', petang);
      final quranOrthography = await _loadQuranOrthographyOverrides();
      final pagiSplit = _splitDailyDzikirItems(
        'pagi',
        pagiNormalized.$2,
      );
      final pagiItems = _applyQuranOrthographyOverrides(
        pagiSplit.$1,
        quranOrthography,
      );
      final petangItems = _applyQuranOrthographyOverrides(
        petangNormalized.$2,
        quranOrthography,
      );
      final harianItems = _applyQuranOrthographyOverrides(
        pagiSplit.$2,
        quranOrthography,
      );
      setState(() {
        _pagiIntroItem = pagiNormalized.$1;
        _petangIntroItem = petangNormalized.$1;
        _pagiItems = pagiItems;
        _petangItems = petangItems;
        _harianItems = harianItems;
        _loading = false;
      });
      _ensureValidFocusPages();
      _seedHarianProgressFromLinkedDzikir();
      _syncDzikirTrackerIfCompleted(prefix: 'pagi', items: _pagiItems);
      _syncDzikirTrackerIfCompleted(prefix: 'petang', items: _petangItems);
    } catch (_) {
      if (!mounted) return;
      setState(() {
        _loading = false;
        _error = 'Gagal memuat dzikir dari server';
      });
    }
  }

  (Map<String, dynamic>?, List<Map<String, dynamic>>) _normalizeRumayshoDzikir(
    String prefix,
    List<Map<String, dynamic>> rawItems,
  ) {
    if (prefix != 'pagi' && prefix != 'petang') {
      return (null, List<Map<String, dynamic>>.from(rawItems));
    }

    final items =
        rawItems.map((item) => Map<String, dynamic>.from(item)).toList();
    Map<String, dynamic>? intro;

    if (items.isNotEmpty && _isTaawwudzItem(items.first)) {
      intro = items.removeAt(0);
    }

    final normalized = <Map<String, dynamic>>[];
    for (var i = 0; i < items.length; i++) {
      if (i + 2 < items.length &&
          _isIkhlasItem(items[i]) &&
          _isFalaqItem(items[i + 1]) &&
          _isNasItem(items[i + 2])) {
        normalized.add({
          'id': '${prefix}_quls',
          'arab': [
            items[i]['arab']?.toString().trim() ?? '',
            items[i + 1]['arab']?.toString().trim() ?? '',
            items[i + 2]['arab']?.toString().trim() ?? '',
          ].join('\n\n'),
          'indo': [
            items[i]['indo']?.toString().trim() ?? '',
            items[i + 1]['indo']?.toString().trim() ?? '',
            items[i + 2]['indo']?.toString().trim() ?? '',
          ].join('\n\n'),
          'ulang': 3,
        });
        i += 2;
        continue;
      }
      normalized.add(items[i]);
    }

    return (intro, normalized);
  }

  Future<Map<String, String>> _loadQuranOrthographyOverrides() async {
    final overrides = <String, String>{};

    try {
      final baqarah = await MuslimApiService.instance.getSurah(2);
      final ayat = List<Map<String, dynamic>>.from(baqarah?['ayat'] ?? []);
      if (ayat.length >= 255) {
        final ayatKursi = ayat[254]['teksArab']?.toString().trim() ?? '';
        if (ayatKursi.isNotEmpty) {
          overrides['ayat_kursi'] = ayatKursi;
        }
      }
    } catch (_) {}

    try {
      final quls = <String>[];
      for (final surahId in const [112, 113, 114]) {
        final surah = await MuslimApiService.instance.getSurah(surahId);
        final verses = List<Map<String, dynamic>>.from(surah?['ayat'] ?? []);
        if (verses.isEmpty) continue;
        final text = verses
            .map((verse) => verse['teksArab']?.toString().trim() ?? '')
            .where((text) => text.isNotEmpty)
            .join(' ');
        if (text.isEmpty) continue;
        quls.add('$_quranBismillah\n$text');
      }
      if (quls.length == 3) {
        overrides['quls'] = quls.join('\n\n');
      }
    } catch (_) {}

    return overrides;
  }

  (List<Map<String, dynamic>>, List<Map<String, dynamic>>)
      _splitDailyDzikirItems(
    String prefix,
    List<Map<String, dynamic>> items,
  ) {
    if (prefix != 'pagi') {
      return (List<Map<String, dynamic>>.from(items), <Map<String, dynamic>>[]);
    }

    final mainItems = <Map<String, dynamic>>[];
    final dailyItems = <Map<String, dynamic>>[];
    for (var i = 0; i < items.length; i++) {
      final sourceNumber = i + 1;
      final item = items[i];
      final copied = Map<String, dynamic>.from(item);
      // Rumaysho dzikir pagi keeps [15] and [18] as "dalam sehari".
      // [16] and [17] stay in the morning flow.
      if (sourceNumber == 15 || sourceNumber == 18) {
        dailyItems.add(copied);
      } else {
        mainItems.add(copied);
      }
    }
    return (mainItems, dailyItems);
  }

  List<Map<String, dynamic>> _applyQuranOrthographyOverrides(
    List<Map<String, dynamic>> items,
    Map<String, String> overrides,
  ) {
    return items.map((item) {
      final next = Map<String, dynamic>.from(item);
      final arab = next['arab']?.toString() ?? '';
      final id = next['id']?.toString() ?? '';

      if (_isAyatKursiItem(next) &&
          overrides['ayat_kursi']?.isNotEmpty == true) {
        next['arab'] = overrides['ayat_kursi'];
      } else if (id.endsWith('_quls') &&
          overrides['quls']?.isNotEmpty == true) {
        next['arab'] = overrides['quls'];
      } else {
        next['arab'] = arab;
      }

      return next;
    }).toList();
  }

  bool _isTaawwudzItem(Map<String, dynamic> item) {
    final arab = item['arab']?.toString() ?? '';
    return arab.contains('أَعُوذُ بِاللَّهِ مِنَ الشَّيْطَانِ الرَّجِيمِ');
  }

  bool _isAyatKursiItem(Map<String, dynamic> item) {
    final arab = item['arab']?.toString() ?? '';
    return arab.contains('اللَّهُ لاَ إِلَهَ إِلاَّ هُوَ الْحَيُّ الْقَيُّومُ');
  }

  bool _isIkhlasItem(Map<String, dynamic> item) {
    final arab = item['arab']?.toString() ?? '';
    return arab.contains('قُلْ هُوَ اللَّهُ أَحَدٌ');
  }

  bool _isFalaqItem(Map<String, dynamic> item) {
    final arab = item['arab']?.toString() ?? '';
    return arab.contains('قُلْ أَعُوذُ بِرَبِّ الْفَلَقِ');
  }

  bool _isNasItem(Map<String, dynamic> item) {
    final arab = item['arab']?.toString() ?? '';
    return arab.contains('قُلْ أَعُوذُ بِرَبِّ النَّاسِ');
  }

  bool _isDailyHundredTauhidItem(Map<String, dynamic> item) {
    final arab = item['arab']?.toString() ?? '';
    final ulang = (item['ulang'] as num?)?.toInt() ?? 1;
    return ulang == 100 &&
        arab.contains('لاَ إِلَهَ إِلاَّ اللهُ وَحْدَهُ لاَ شَرِيْكَ لَهُ');
  }

  bool _isDailyIstighfarItem(Map<String, dynamic> item) {
    final arab = item['arab']?.toString() ?? '';
    final ulang = (item['ulang'] as num?)?.toInt() ?? 1;
    return ulang == 100 &&
        arab.contains('أَسْتَغْفِرُ اللَّهَ') &&
        arab.contains('وَأَتُوبُ إِلَيْهِ');
  }

  bool _isLinkedTenTauhidItem(Map<String, dynamic> item) {
    final arab = item['arab']?.toString() ?? '';
    final ulang = (item['ulang'] as num?)?.toInt() ?? 1;
    return ulang == 10 &&
        arab.contains('لاَ إِلَهَ إِلاَّ اللهُ وَحْدَهُ لاَ شَرِيْكَ لَهُ');
  }

  String _dzikirTargetBadgeLabel(Map<String, dynamic> item, int target) {
    if (_isDailyHundredTauhidItem(item) || _isDailyIstighfarItem(item)) {
      return '$target X / HARI';
    }
    return '$target KALI';
  }

  String? _dzikirScopeNote(Map<String, dynamic> item) {
    if (_isDailyHundredTauhidItem(item) || _isDailyIstighfarItem(item)) {
      return 'Dibaca 100 kali dalam sehari, tidak harus selesai dalam satu duduk.';
    }
    return null;
  }

  void _seedHarianProgressFromLinkedDzikir() {
    final harianIndex = _harianItems.indexWhere(_isDailyHundredTauhidItem);
    if (harianIndex == -1) return;

    final harianItem = _harianItems[harianIndex];
    final harianTarget = (harianItem['ulang'] as num?)?.toInt() ?? 1;
    final harianKey =
        '${_resolveDzikirId(harianItem, 'harian', harianIndex)}_$_todayKey';
    final existing = _counterBox.get(harianKey);

    var desired = 0;
    final pagiIndex = _pagiItems.indexWhere(_isLinkedTenTauhidItem);
    if (pagiIndex != -1) {
      final pagiItem = _pagiItems[pagiIndex];
      desired += _getCounter(
        _resolveDzikirId(pagiItem, 'pagi', pagiIndex),
        (pagiItem['ulang'] as num?)?.toInt() ?? 1,
        prefix: 'pagi',
      ).count;
    }
    final petangIndex = _petangItems.indexWhere(_isLinkedTenTauhidItem);
    if (petangIndex != -1) {
      final petangItem = _petangItems[petangIndex];
      desired += _getCounter(
        _resolveDzikirId(petangItem, 'petang', petangIndex),
        (petangItem['ulang'] as num?)?.toInt() ?? 1,
        prefix: 'petang',
      ).count;
    }
    desired = desired.clamp(0, harianTarget);

    if (existing == null) {
      if (desired == 0) return;
      _counterBox.put(
        harianKey,
        DzikirCounter(
          dzikirId: _resolveDzikirId(harianItem, 'harian', harianIndex),
          date: _todayKey,
          count: desired,
          target: harianTarget,
        ),
      );
      return;
    }

    if (existing.count >= desired) return;
    existing.count = desired;
    existing.target = harianTarget;
    existing.save();
  }

  void _syncDailyProgressFromLinkedIncrement(Map<String, dynamic> item) {
    if (!_isLinkedTenTauhidItem(item)) return;

    final harianIndex = _harianItems.indexWhere(_isDailyHundredTauhidItem);
    if (harianIndex == -1) return;

    final harianItem = _harianItems[harianIndex];
    final dzikirId = _resolveDzikirId(harianItem, 'harian', harianIndex);
    final target = (harianItem['ulang'] as num?)?.toInt() ?? 1;
    final key = '${dzikirId}_$_todayKey';
    final counter = _counterBox.get(key);

    if (counter == null) {
      _counterBox.put(
        key,
        DzikirCounter(
          dzikirId: dzikirId,
          date: _todayKey,
          count: 1,
          target: target,
        ),
      );
      setState(() {});
      return;
    }

    if (counter.count >= target) return;
    counter.count++;
    counter.target = target;
    counter.save();
    setState(() {});
  }

  void _showArabicFontSettings() {
    final settingsBox = Hive.box<AppSettings>(HiveBoxes.settings);
    final settings = settingsBox.get('default') ?? AppSettings();
    if (!settings.isInBox) {
      settingsBox.put('default', settings);
    }
    double arabicFontSize = settings.arabicFontSize;

    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),
                const Text('Ukuran Font Arab'),
                Slider(
                  value: arabicFontSize,
                  min: 16,
                  max: 40,
                  divisions: 12,
                  label: '${arabicFontSize.round()}pt',
                  activeColor: AppColors.primary,
                  onChanged: (value) {
                    setModalState(() => arabicFontSize = value);
                    settings.arabicFontSize = value;
                    if (settings.isInBox) {
                      settings.save();
                    } else {
                      settingsBox.put('default', settings);
                    }
                  },
                ),
                const SizedBox(height: 8),
              ],
            ),
          );
        },
      ),
    );
  }

  void _ensureValidFocusPages() {
    _clampFocusPageForPrefix(
      'pagi',
      _pagiItems.length + (_pagiIntroItem != null ? 1 : 0),
    );
    _clampFocusPageForPrefix(
      'petang',
      _petangItems.length + (_petangIntroItem != null ? 1 : 0),
    );
    _clampFocusPageForPrefix('harian', _harianItems.length);
  }

  void _clampFocusPageForPrefix(String prefix, int itemLength) {
    final maxIndex = itemLength > 0 ? itemLength - 1 : 0;
    final current = _focusPageIndex[prefix] ?? 0;
    final next = current > maxIndex ? maxIndex : current;
    _focusPageIndex[prefix] = next;

    final controller = _pageControllers[prefix];
    if (controller == null || !controller.hasClients) return;
    if (controller.page?.round() == next) return;

    WidgetsBinding.instance.addPostFrameCallback((_) {
      if (!mounted || !controller.hasClients) return;
      controller.jumpToPage(next);
    });
  }

  DzikirCounter _getCounter(
    String dzikirId,
    int target, {
    required String prefix,
  }) {
    final scopeKey = _counterScopeKeyForPrefix(prefix);
    final dateKey = _counterDateKeyForPrefix(prefix);
    final key = '${dzikirId}_$scopeKey';
    return _counterBox.get(key) ??
        DzikirCounter(
          dzikirId: dzikirId,
          date: dateKey,
          count: 0,
          target: target,
        );
  }

  bool _increment(
    String dzikirId,
    int target, {
    required String prefix,
    required bool hapticEnabled,
  }) {
    _refreshTodayScope();
    final scopeKey = _counterScopeKeyForPrefix(prefix);
    final dateKey = _counterDateKeyForPrefix(prefix);
    final key = '${dzikirId}_$scopeKey';
    var counter = _counterBox.get(key);
    final wasComplete = counter != null && counter.count >= counter.target;

    if (counter == null) {
      counter = DzikirCounter(
        dzikirId: dzikirId,
        date: dateKey,
        count: 1,
        target: target,
      );
      _counterBox.put(key, counter);
    } else if (counter.count < counter.target) {
      counter.count++;
      counter.save();
    }

    final isCompleteNow = counter.count >= counter.target;
    if (hapticEnabled) {
      HapticFeedback.lightImpact();
    }
    setState(() {});
    return !wasComplete && isCompleteNow;
  }

  bool _isDzikirGroupComplete(
    String prefix,
    List<Map<String, dynamic>> items,
  ) {
    if (items.isEmpty) return false;
    for (int i = 0; i < items.length; i++) {
      final item = items[i];
      final dzikirId = _resolveDzikirId(item, prefix, i);
      final target = (item['ulang'] as num?)?.toInt() ?? 1;
      final counter = _getCounter(dzikirId, target, prefix: prefix);
      if (counter.count < target) {
        return false;
      }
    }
    return true;
  }

  void _syncDzikirTrackerIfCompleted({
    required String prefix,
    required List<Map<String, dynamic>> items,
  }) {
    _refreshTodayScope();
    if (widget.isSimpleModeTab) return;
    if (prefix != 'pagi' && prefix != 'petang') return;
    if (!_isDzikirGroupComplete(prefix, items)) return;

    final logBox = Hive.box<DailyWorshipLog>(HiveBoxes.worshipLogs);
    var log = logBox.get(_todayKey);
    if (log == null) {
      log = DailyWorshipLog(
        date: _todayKey,
        shalatLogs: <String, ShalatLog>{
          'subuh': ShalatLog(),
          'dzuhur': ShalatLog(),
          'ashar': ShalatLog(),
          'maghrib': ShalatLog(),
          'isya': ShalatLog(),
        },
      );
      logBox.put(_todayKey, log);
    }
    log.dzikirLog ??= DzikirLog();

    final dzikirLog = log.dzikirLog!;
    bool changed = false;
    if (prefix == 'pagi' && !dzikirLog.pagi) {
      dzikirLog.pagi = true;
      changed = true;
    }
    if (prefix == 'petang' && !dzikirLog.petang) {
      dzikirLog.petang = true;
      changed = true;
    }

    if (changed) {
      log.save();
    }
  }

  @override
  Widget build(BuildContext context) {
    final isDark = Theme.of(context).brightness == Brightness.dark;

    return ValueListenableBuilder<Box<AppSettings>>(
      valueListenable: Hive.box<AppSettings>(HiveBoxes.settings)
          .listenable(keys: ['default']),
      builder: (_, settingsBox, __) {
        final settings = settingsBox.get('default') ?? AppSettings();
        final isFocusMode = settings.dzikirDisplayMode == 'focus';

        return Scaffold(
          appBar: AppBar(
            automaticallyImplyLeading: false,
            leading: IconButton(
              icon: const Icon(LucideIcons.chevronLeft),
              tooltip: 'Kembali',
              onPressed: () {
                context.go(widget.isSimpleModeTab ? '/' : '/tools');
              },
            ),
            title: const Text('Dzikir Harian'),
            actionsPadding: const EdgeInsets.only(right: 8),
            actions: [
              IconButton(
                onPressed: _loadData,
                icon: const Icon(LucideIcons.refreshCw),
                tooltip: 'Muat ulang',
              ),
              IconButton(
                onPressed: _showArabicFontSettings,
                icon: const Icon(LucideIcons.settings2),
                tooltip: 'Pengaturan tampilan',
              ),
            ],
            bottom: TabBar(
              controller: _tabController,
              labelColor: AppColors.primary,
              unselectedLabelColor: isDark
                  ? AppColors.textSecondaryDark
                  : AppColors.textSecondaryLight,
              indicatorColor: AppColors.primary,
              indicatorWeight: 3,
              labelStyle:
                  const TextStyle(fontWeight: FontWeight.w700, fontSize: 13),
              tabs: const [
                Tab(text: 'Pagi'),
                Tab(text: 'Petang'),
                Tab(text: 'Harian'),
              ],
            ),
          ),
          body: SafeArea(
            top: false,
            bottom: true,
            child: _loading
                ? const Center(child: CircularProgressIndicator())
                : _error != null
                    ? _buildErrorState(isDark)
                    : TabBarView(
                        controller: _tabController,
                        children: [
                          isFocusMode
                              ? _buildFocusModeTab(
                                  context,
                                  isDark,
                                  settings,
                                  items: _pagiItems,
                                  introItem: _pagiIntroItem,
                                  prefix: 'pagi',
                                  title: 'Dzikir Pagi',
                                  subtitle:
                                      'Dibaca setelah shalat Subuh hingga terbit matahari.',
                                )
                              : _buildDzikirList(
                                  context,
                                  isDark,
                                  settings,
                                  _pagiItems,
                                  _pagiIntroItem,
                                  'pagi',
                                  'Dzikir Pagi',
                                  'Dibaca setelah shalat Subuh hingga terbit matahari.',
                                ),
                          isFocusMode
                              ? _buildFocusModeTab(
                                  context,
                                  isDark,
                                  settings,
                                  items: _petangItems,
                                  introItem: _petangIntroItem,
                                  prefix: 'petang',
                                  title: 'Dzikir Petang',
                                  subtitle:
                                      'Dibaca setelah Ashar hingga terbenam matahari.',
                                )
                              : _buildDzikirList(
                                  context,
                                  isDark,
                                  settings,
                                  _petangItems,
                                  _petangIntroItem,
                                  'petang',
                                  'Dzikir Petang',
                                  'Dibaca setelah Ashar hingga terbenam matahari.',
                                ),
                          isFocusMode
                              ? _buildFocusModeTab(
                                  context,
                                  isDark,
                                  settings,
                                  items: _harianItems,
                                  introItem: null,
                                  prefix: 'harian',
                                  title: 'Dzikir Harian',
                                  subtitle:
                                      'Target dzikir yang dapat dicicil sepanjang hari. Progress dari Dzikir Pagi dan Petang ikut terhitung di sini.',
                                )
                              : _buildDzikirList(
                                  context,
                                  isDark,
                                  settings,
                                  _harianItems,
                                  null,
                                  'harian',
                                  'Dzikir Harian',
                                  'Target dzikir yang dapat dicicil sepanjang hari. Progress dari Dzikir Pagi dan Petang ikut terhitung di sini.',
                                ),
                        ],
                      ),
          ),
        );
      },
    );
  }

  Widget _buildErrorState(bool isDark) {
    return Center(
      child: Padding(
        padding: const EdgeInsets.all(24),
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            Icon(
              LucideIcons.wifiOff,
              size: 42,
              color: isDark
                  ? AppColors.textSecondaryDark
                  : AppColors.textSecondaryLight,
            ),
            const SizedBox(height: 12),
            Text(
              _error!,
              textAlign: TextAlign.center,
              style: TextStyle(
                color: isDark
                    ? AppColors.textSecondaryDark
                    : AppColors.textSecondaryLight,
              ),
            ),
          ],
        ),
      ),
    );
  }

  Widget _buildDzikirList(
    BuildContext context,
    bool isDark,
    AppSettings settings,
    List<Map<String, dynamic>> items,
    Map<String, dynamic>? introItem,
    String prefix,
    String title,
    String subtitle,
  ) {
    if (items.isEmpty) {
      return _buildEmptyState(
        isDark,
        title: 'Belum ada data dzikir',
        subtitle: 'Data untuk tab ini belum tersedia.',
      );
    }

    return ListView.builder(
      padding: const EdgeInsets.all(16),
      itemCount: items.length + 1,
      itemBuilder: (context, index) {
        if (index == 0) {
          return Padding(
            padding: const EdgeInsets.only(bottom: 20),
            child: Column(
              children: [
                Text(
                  title,
                  style: const TextStyle(
                    fontSize: 22,
                    fontWeight: FontWeight.w800,
                  ),
                ),
                const SizedBox(height: 4),
                Text(
                  subtitle,
                  textAlign: TextAlign.center,
                  style: TextStyle(
                    color: isDark
                        ? AppColors.textSecondaryDark
                        : AppColors.textSecondaryLight,
                    fontSize: 13,
                  ),
                ),
                if (introItem != null) ...[
                  const SizedBox(height: 16),
                  _buildIntroRemembrance(isDark, introItem),
                ],
              ],
            ),
          );
        }

        final item = items[index - 1];
        final dzikirId = _resolveDzikirId(item, prefix, index - 1);
        final target = (item['ulang'] as num?)?.toInt() ?? 1;
        final counter = _getCounter(dzikirId, target, prefix: prefix);
        final isComplete = counter.count >= counter.target;

        return Padding(
          padding: const EdgeInsets.only(bottom: 16),
          child: Container(
            padding: const EdgeInsets.all(20),
            decoration: BoxDecoration(
              color: isDark ? AppColors.surfaceDark : AppColors.surfaceLight,
              borderRadius: BorderRadius.circular(16),
              border: Border.all(
                color: isComplete
                    ? AppColors.primary.withValues(alpha: 0.3)
                    : (isDark
                        ? AppColors.primary.withValues(alpha: 0.08)
                        : AppColors.cream),
              ),
            ),
            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.12),
                        borderRadius: BorderRadius.circular(50),
                      ),
                      child: Text(
                        _dzikirTargetBadgeLabel(item, target),
                        style: const TextStyle(
                          fontSize: 10,
                          fontWeight: FontWeight.w700,
                          color: AppColors.primary,
                        ),
                      ),
                    ),
                    Text(
                      (index).toString().padLeft(2, '0'),
                      style: TextStyle(
                        fontSize: 14,
                        fontWeight: FontWeight.w600,
                        color: isDark
                            ? AppColors.textSecondaryDark
                            : AppColors.textSecondaryLight,
                      ),
                    ),
                  ],
                ),
                const SizedBox(height: 16),
                SizedBox(
                  width: double.infinity,
                  child: ArabicText(
                    item['arab']?.toString() ?? '',
                    textAlign: TextAlign.right,
                    baseFontSize: 24,
                    fontWeight: FontWeight.w400,
                    height: 2.0,
                  ),
                ),
                const SizedBox(height: 10),
                Text(
                  '"${item['indo']?.toString() ?? ''}"',
                  style: TextStyle(
                    fontSize: 13,
                    color: isDark
                        ? AppColors.textSecondaryDark
                        : AppColors.textSecondaryLight,
                    height: 1.5,
                  ),
                ),
                if (_dzikirScopeNote(item) case final note?) ...[
                  const SizedBox(height: 8),
                  Text(
                    note,
                    style: TextStyle(
                      fontSize: 11,
                      fontWeight: FontWeight.w600,
                      color: AppColors.primary.withValues(alpha: 0.8),
                      height: 1.45,
                    ),
                  ),
                ],
                const SizedBox(height: 16),
                GestureDetector(
                  onTap: () async {
                    final becameComplete = _increment(
                      dzikirId,
                      target,
                      prefix: prefix,
                      hapticEnabled: settings.dzikirHapticOnCount,
                    );
                    _syncDailyProgressFromLinkedIncrement(item);
                    if (becameComplete) {
                      _syncDzikirTrackerIfCompleted(
                        prefix: prefix,
                        items: items,
                      );
                    }
                  },
                  child: Container(
                    width: double.infinity,
                    padding: const EdgeInsets.symmetric(vertical: 14),
                    decoration: BoxDecoration(
                      color: isComplete
                          ? AppColors.primary.withValues(alpha: 0.15)
                          : AppColors.primary,
                      borderRadius: BorderRadius.circular(50),
                    ),
                    child: Row(
                      mainAxisAlignment: MainAxisAlignment.center,
                      children: [
                        Icon(
                          isComplete
                              ? LucideIcons.check
                              : LucideIcons.fingerprint,
                          size: 18,
                          color: isComplete
                              ? AppColors.primary
                              : AppColors.onPrimary,
                        ),
                        const SizedBox(width: 8),
                        Text(
                          isComplete ? 'Selesai' : '${counter.count} / $target',
                          style: TextStyle(
                            fontSize: 15,
                            fontWeight: FontWeight.w700,
                            color: isComplete
                                ? AppColors.primary
                                : AppColors.onPrimary,
                          ),
                        ),
                      ],
                    ),
                  ),
                ),
              ],
            ),
          ),
        );
      },
    );
  }

  Widget _buildFocusModeTab(
    BuildContext context,
    bool isDark,
    AppSettings settings, {
    required List<Map<String, dynamic>> items,
    required Map<String, dynamic>? introItem,
    required String prefix,
    required String title,
    required String subtitle,
  }) {
    if (items.isEmpty) {
      return _buildEmptyState(
        isDark,
        title: 'Belum ada data dzikir',
        subtitle: 'Data untuk tab ini belum tersedia.',
      );
    }

    final controller = _pageControllers[prefix]!;
    final introOffset = introItem != null ? 1 : 0;
    final pageCount = items.length + introOffset;
    final rawCurrent = _focusPageIndex[prefix] ?? 0;
    final currentPage = rawCurrent.clamp(0, pageCount - 1);
    final isIntroPage = introItem != null && currentPage == 0;
    final currentIndex = introItem != null ? currentPage - 1 : currentPage;

    DzikirCounter? currentCounter;
    int currentTarget = 0;
    bool isComplete = false;
    if (!isIntroPage) {
      final currentItem = items[currentIndex];
      final currentId = _resolveDzikirId(currentItem, prefix, currentIndex);
      currentTarget = (currentItem['ulang'] as num?)?.toInt() ?? 1;
      currentCounter = _getCounter(currentId, currentTarget, prefix: prefix);
      isComplete = currentCounter.count >= currentCounter.target;
    }

    final actionLabel = isIntroPage
        ? 'Lanjut'
        : (isComplete
            ? 'Selesai'
            : '${currentCounter!.count} / $currentTarget');
    final actionIcon = isIntroPage
        ? LucideIcons.chevronRight
        : (isComplete ? LucideIcons.check : LucideIcons.fingerprint);

    return Padding(
      padding: const EdgeInsets.fromLTRB(16, 16, 16, 16),
      child: Column(
        children: [
          Text(
            title,
            style: const TextStyle(fontSize: 22, fontWeight: FontWeight.w800),
          ),
          const SizedBox(height: 4),
          Text(
            subtitle,
            textAlign: TextAlign.center,
            style: TextStyle(
              color: isDark
                  ? AppColors.textSecondaryDark
                  : AppColors.textSecondaryLight,
              fontSize: 13,
            ),
          ),
          const SizedBox(height: 12),
          Container(
            padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
            decoration: BoxDecoration(
              color: AppColors.primary.withValues(alpha: 0.12),
              borderRadius: BorderRadius.circular(50),
            ),
            child: Text(
              isIntroPage
                  ? 'Pembuka'
                  : 'Item ${currentIndex + 1} dari ${items.length}',
              style: const TextStyle(
                fontSize: 12,
                fontWeight: FontWeight.w700,
                color: AppColors.primary,
              ),
            ),
          ),
          const SizedBox(height: 12),
          Expanded(
            child: Stack(
              children: [
                LayoutBuilder(
                  builder: (context, constraints) {
                    final maxCardHeight = constraints.maxHeight > 92
                        ? constraints.maxHeight - 92
                        : constraints.maxHeight;

                    return PageView.builder(
                      controller: controller,
                      itemCount: pageCount,
                      onPageChanged: (index) {
                        setState(() {
                          _focusPageIndex[prefix] = index;
                        });
                      },
                      itemBuilder: (context, index) {
                        if (introItem != null && index == 0) {
                          return Padding(
                            padding: const EdgeInsets.only(bottom: 92),
                            child: Align(
                              alignment: Alignment.topCenter,
                              child: ConstrainedBox(
                                constraints: BoxConstraints(
                                  maxHeight: maxCardHeight,
                                ),
                                child: _buildFocusIntroCard(
                                  isDark,
                                  item: introItem,
                                ),
                              ),
                            ),
                          );
                        }

                        final itemIndex = introItem != null ? index - 1 : index;
                        final item = items[itemIndex];
                        final dzikirId =
                            _resolveDzikirId(item, prefix, itemIndex);
                        final target = (item['ulang'] as num?)?.toInt() ?? 1;
                        final counter =
                            _getCounter(dzikirId, target, prefix: prefix);
                        final complete = counter.count >= counter.target;
                        return Padding(
                          padding: const EdgeInsets.only(bottom: 92),
                          child: Align(
                            alignment: Alignment.topCenter,
                            child: ConstrainedBox(
                              constraints: BoxConstraints(
                                maxHeight: maxCardHeight,
                              ),
                              child: _buildFocusCard(
                                isDark,
                                item: item,
                                index: itemIndex,
                                target: target,
                                counter: counter,
                                isComplete: complete,
                              ),
                            ),
                          ),
                        );
                      },
                    );
                  },
                ),
                if (settings.dzikirCounterButtonPosition == 'fabCircle')
                  Positioned(
                    right: 8,
                    bottom: 12,
                    child: _buildFocusCounterFab(
                      isDark,
                      isComplete: isComplete,
                      icon: actionIcon,
                      label: isIntroPage
                          ? actionLabel
                          : (isComplete
                              ? 'Selesai'
                              : '${currentCounter!.count}/$currentTarget'),
                      onTap: () => _onFocusCounterTap(
                        context,
                        settings,
                        prefix,
                        items,
                        introItem: introItem,
                      ),
                    ),
                  )
                else
                  Positioned(
                    left: 0,
                    right: 0,
                    bottom: 12,
                    child: _buildFocusCounterPill(
                      isComplete: isComplete,
                      icon: actionIcon,
                      label: actionLabel,
                      onTap: () => _onFocusCounterTap(
                        context,
                        settings,
                        prefix,
                        items,
                        introItem: introItem,
                      ),
                    ),
                  ),
              ],
            ),
          ),
        ],
      ),
    );
  }

  Widget _buildIntroRemembrance(
    bool isDark,
    Map<String, dynamic> item,
  ) {
    return Container(
      width: double.infinity,
      padding: const EdgeInsets.all(16),
      decoration: BoxDecoration(
        color: isDark
            ? AppColors.primary.withValues(alpha: 0.08)
            : AppColors.primary.withValues(alpha: 0.06),
        borderRadius: BorderRadius.circular(16),
        border: Border.all(
          color: AppColors.primary.withValues(alpha: 0.12),
        ),
      ),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          const Text(
            'Pembuka',
            style: TextStyle(
              fontSize: 11,
              fontWeight: FontWeight.w700,
              letterSpacing: 1.0,
              color: AppColors.primary,
            ),
          ),
          const SizedBox(height: 10),
          ArabicText(
            item['arab']?.toString() ?? '',
            textAlign: TextAlign.right,
            baseFontSize: 20,
            fontWeight: FontWeight.w400,
            height: 1.9,
          ),
          const SizedBox(height: 8),
          Text(
            '"${item['indo']?.toString() ?? ''}"',
            style: TextStyle(
              fontSize: 13,
              height: 1.5,
              color: isDark
                  ? AppColors.textSecondaryDark
                  : AppColors.textSecondaryLight,
            ),
          ),
        ],
      ),
    );
  }

  Widget _buildFocusIntroCard(
    bool isDark, {
    required Map<String, dynamic> item,
  }) {
    return Container(
      width: double.infinity,
      padding: const EdgeInsets.all(20),
      decoration: BoxDecoration(
        color: isDark ? AppColors.surfaceDark : AppColors.surfaceLight,
        borderRadius: BorderRadius.circular(20),
        border: Border.all(
          color: isDark
              ? AppColors.primary.withValues(alpha: 0.08)
              : AppColors.cream,
        ),
      ),
      child: SingleChildScrollView(
        physics: const ClampingScrollPhysics(),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Container(
              padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 4),
              decoration: BoxDecoration(
                color: AppColors.primary.withValues(alpha: 0.12),
                borderRadius: BorderRadius.circular(50),
              ),
              child: const Text(
                'PEMBUKA',
                style: TextStyle(
                  fontSize: 10,
                  fontWeight: FontWeight.w700,
                  color: AppColors.primary,
                ),
              ),
            ),
            const SizedBox(height: 20),
            SizedBox(
              width: double.infinity,
              child: ArabicText(
                item['arab']?.toString() ?? '',
                textAlign: TextAlign.right,
                baseFontSize: 28,
                fontWeight: FontWeight.w400,
                height: 2.0,
              ),
            ),
            const SizedBox(height: 14),
            Text(
              '"${item['indo']?.toString() ?? ''}"',
              style: TextStyle(
                fontSize: 14,
                color: isDark
                    ? AppColors.textSecondaryDark
                    : AppColors.textSecondaryLight,
                height: 1.6,
              ),
            ),
          ],
        ),
      ),
    );
  }

  Widget _buildFocusCard(
    bool isDark, {
    required Map<String, dynamic> item,
    required int index,
    required int target,
    required DzikirCounter counter,
    required bool isComplete,
  }) {
    return Container(
      width: double.infinity,
      padding: const EdgeInsets.all(20),
      decoration: BoxDecoration(
        color: isDark ? AppColors.surfaceDark : AppColors.surfaceLight,
        borderRadius: BorderRadius.circular(20),
        border: Border.all(
          color: isComplete
              ? AppColors.primary.withValues(alpha: 0.3)
              : (isDark
                  ? AppColors.primary.withValues(alpha: 0.08)
                  : AppColors.cream),
        ),
      ),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        mainAxisSize: MainAxisSize.min,
        children: [
          Row(
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
            children: [
              Container(
                padding:
                    const EdgeInsets.symmetric(horizontal: 10, vertical: 4),
                decoration: BoxDecoration(
                  color: AppColors.primary.withValues(alpha: 0.12),
                  borderRadius: BorderRadius.circular(50),
                ),
                child: Text(
                  _dzikirTargetBadgeLabel(item, target),
                  style: const TextStyle(
                    fontSize: 10,
                    fontWeight: FontWeight.w700,
                    color: AppColors.primary,
                  ),
                ),
              ),
              Text(
                (index + 1).toString().padLeft(2, '0'),
                style: TextStyle(
                  fontSize: 14,
                  fontWeight: FontWeight.w600,
                  color: isDark
                      ? AppColors.textSecondaryDark
                      : AppColors.textSecondaryLight,
                ),
              ),
            ],
          ),
          const SizedBox(height: 20),
          Flexible(
            fit: FlexFit.loose,
            child: SingleChildScrollView(
              physics: const ClampingScrollPhysics(),
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                mainAxisSize: MainAxisSize.min,
                children: [
                  SizedBox(
                    width: double.infinity,
                    child: ArabicText(
                      item['arab']?.toString() ?? '',
                      textAlign: TextAlign.right,
                      baseFontSize: 28,
                      fontWeight: FontWeight.w400,
                      height: 2.0,
                    ),
                  ),
                  const SizedBox(height: 14),
                  Text(
                    '"${item['indo']?.toString() ?? ''}"',
                    style: TextStyle(
                      fontSize: 14,
                      color: isDark
                          ? AppColors.textSecondaryDark
                          : AppColors.textSecondaryLight,
                      height: 1.6,
                    ),
                  ),
                  if (_dzikirScopeNote(item) case final note?) ...[
                    const SizedBox(height: 10),
                    Text(
                      note,
                      style: TextStyle(
                        fontSize: 12,
                        fontWeight: FontWeight.w600,
                        color: AppColors.primary.withValues(alpha: 0.82),
                        height: 1.45,
                      ),
                    ),
                  ],
                  const SizedBox(height: 12),
                  if (isComplete)
                    Container(
                      padding: const EdgeInsets.symmetric(
                        horizontal: 12,
                        vertical: 6,
                      ),
                      decoration: BoxDecoration(
                        color: AppColors.primary.withValues(alpha: 0.15),
                        borderRadius: BorderRadius.circular(50),
                      ),
                      child: Text(
                        'Selesai (${counter.count}/$target)',
                        style: const TextStyle(
                          color: AppColors.primary,
                          fontWeight: FontWeight.w700,
                          fontSize: 12,
                        ),
                      ),
                    ),
                ],
              ),
            ),
          ),
        ],
      ),
    );
  }

  Widget _buildFocusCounterPill({
    required bool isComplete,
    required IconData icon,
    required String label,
    required VoidCallback onTap,
  }) {
    return GestureDetector(
      onTap: onTap,
      child: Container(
        margin: const EdgeInsets.symmetric(horizontal: 8),
        padding: const EdgeInsets.symmetric(vertical: 14),
        decoration: BoxDecoration(
          color: isComplete
              ? AppColors.primary.withValues(alpha: 0.15)
              : AppColors.primary,
          borderRadius: BorderRadius.circular(50),
        ),
        child: Row(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Icon(
              icon,
              size: 18,
              color: isComplete ? AppColors.primary : AppColors.onPrimary,
            ),
            const SizedBox(width: 8),
            Text(
              label,
              style: TextStyle(
                fontSize: 15,
                fontWeight: FontWeight.w700,
                color: isComplete ? AppColors.primary : AppColors.onPrimary,
              ),
            ),
          ],
        ),
      ),
    );
  }

  Widget _buildFocusCounterFab(
    bool isDark, {
    required bool isComplete,
    required IconData icon,
    required String label,
    required VoidCallback onTap,
  }) {
    return GestureDetector(
      onTap: onTap,
      child: Container(
        width: 72,
        height: 72,
        decoration: BoxDecoration(
          shape: BoxShape.circle,
          color: isComplete
              ? AppColors.primary.withValues(alpha: 0.15)
              : AppColors.primary,
          boxShadow: [
            BoxShadow(
              color: (isDark ? Colors.black : Colors.black26)
                  .withValues(alpha: 0.14),
              blurRadius: 18,
              offset: const Offset(0, 6),
            ),
          ],
        ),
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Icon(
              icon,
              size: 18,
              color: isComplete ? AppColors.primary : AppColors.onPrimary,
            ),
            const SizedBox(height: 2),
            Text(
              label,
              style: TextStyle(
                fontSize: 10,
                fontWeight: FontWeight.w700,
                color: isComplete ? AppColors.primary : AppColors.onPrimary,
              ),
              textAlign: TextAlign.center,
            ),
          ],
        ),
      ),
    );
  }

  Future<void> _onFocusCounterTap(
    BuildContext context,
    AppSettings settings,
    String prefix,
    List<Map<String, dynamic>> items, {
    required Map<String, dynamic>? introItem,
  }) async {
    _refreshTodayScope();
    if (items.isEmpty) return;

    final introOffset = introItem != null ? 1 : 0;
    final currentPage =
        (_focusPageIndex[prefix] ?? 0).clamp(0, items.length + introOffset - 1);

    if (introItem != null && currentPage == 0) {
      final controller = _pageControllers[prefix];
      if (controller != null && controller.hasClients) {
        controller.nextPage(
          duration: const Duration(milliseconds: 240),
          curve: Curves.easeOut,
        );
      }
      return;
    }

    final currentIndex = introItem != null ? currentPage - 1 : currentPage;
    final item = items[currentIndex];
    final dzikirId = _resolveDzikirId(item, prefix, currentIndex);
    final target = (item['ulang'] as num?)?.toInt() ?? 1;

    final becameComplete = _increment(
      dzikirId,
      target,
      prefix: prefix,
      hapticEnabled: settings.dzikirHapticOnCount,
    );
    _syncDailyProgressFromLinkedIncrement(item);

    if (!becameComplete) return;

    _syncDzikirTrackerIfCompleted(
      prefix: prefix,
      items: items,
    );

    final isLast = currentIndex == items.length - 1;
    if (settings.dzikirAutoAdvance && !isLast) {
      final controller = _pageControllers[prefix];
      if (controller != null && controller.hasClients) {
        controller.nextPage(
          duration: const Duration(milliseconds: 240),
          curve: Curves.easeOut,
        );
      }
      return;
    }

    if (isLast) {
      ScaffoldMessenger.of(context).showSnackBar(
        const SnackBar(
          content: Text('Semua dzikir pada tab ini selesai'),
          duration: Duration(seconds: 2),
        ),
      );
    }
  }

  String _resolveDzikirId(Map<String, dynamic> item, String prefix, int index) {
    final rawId = item['id']?.toString();
    if (rawId != null && rawId.isNotEmpty) {
      return rawId;
    }
    return '${prefix}_${index + 1}';
  }

  Widget _buildEmptyState(
    bool isDark, {
    required String title,
    required String subtitle,
  }) {
    return Center(
      child: Padding(
        padding: const EdgeInsets.all(24),
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            Icon(
              LucideIcons.inbox,
              size: 42,
              color: isDark
                  ? AppColors.textSecondaryDark
                  : AppColors.textSecondaryLight,
            ),
            const SizedBox(height: 12),
            Text(
              title,
              style: const TextStyle(fontWeight: FontWeight.w700, fontSize: 15),
              textAlign: TextAlign.center,
            ),
            const SizedBox(height: 6),
            Text(
              subtitle,
              style: TextStyle(
                color: isDark
                    ? AppColors.textSecondaryDark
                    : AppColors.textSecondaryLight,
              ),
              textAlign: TextAlign.center,
            ),
          ],
        ),
      ),
    );
  }
}
