import 'package:hive_flutter/hive_flutter.dart';
import 'package:intl/intl.dart';

import '../local/hive_boxes.dart';
import '../local/models/app_settings.dart';

/// Runtime persistence for notification counters and cursors.
class NotificationRuntimeService {
  NotificationRuntimeService._();
  static final NotificationRuntimeService instance =
      NotificationRuntimeService._();

  static const _nonPrayerCountPrefix = 'non_prayer_push_count.';
  static const _lastRemoteSyncKey = 'remote.last_sync_at';
  static const _lastWeeklySummaryKey = 'summary.last_week_key';

  Box get _box => Hive.box(HiveBoxes.notificationRuntime);

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

  int nonPrayerPushCountToday() {
    return (_box.get('$_nonPrayerCountPrefix${_todayKey()}') as int?) ?? 0;
  }

  Future<void> incrementNonPrayerPushCount() async {
    final key = '$_nonPrayerCountPrefix${_todayKey()}';
    final next = ((_box.get(key) as int?) ?? 0) + 1;
    await _box.put(key, next);
  }

  bool isWithinQuietHours(AppSettings settings, {DateTime? now}) {
    final current = now ?? DateTime.now();
    final startParts = _parseHourMinute(settings.quietHoursStart);
    final endParts = _parseHourMinute(settings.quietHoursEnd);
    if (startParts == null || endParts == null) return false;

    final currentMinutes = current.hour * 60 + current.minute;
    final startMinutes = startParts.$1 * 60 + startParts.$2;
    final endMinutes = endParts.$1 * 60 + endParts.$2;

    if (startMinutes == endMinutes) {
      // Same value means quiet-hours disabled.
      return false;
    }
    if (startMinutes < endMinutes) {
      return currentMinutes >= startMinutes && currentMinutes < endMinutes;
    }
    // Overnight interval (e.g. 22:00 -> 05:00).
    return currentMinutes >= startMinutes || currentMinutes < endMinutes;
  }

  bool canSendNonPrayerPush(AppSettings settings, {DateTime? now}) {
    if (!settings.alertsEnabled) return false;
    if (isWithinQuietHours(settings, now: now)) return false;
    return nonPrayerPushCountToday() < settings.maxNonPrayerPushPerDay;
  }

  DateTime? lastRemoteSyncAt() {
    final raw = (_box.get(_lastRemoteSyncKey) ?? '').toString();
    if (raw.isEmpty) return null;
    return DateTime.tryParse(raw);
  }

  Future<void> setLastRemoteSyncAt(DateTime value) async {
    await _box.put(_lastRemoteSyncKey, value.toIso8601String());
  }

  String? lastWeeklySummaryWeekKey() {
    final raw = (_box.get(_lastWeeklySummaryKey) ?? '').toString();
    return raw.isEmpty ? null : raw;
  }

  Future<void> setLastWeeklySummaryWeekKey(String key) async {
    await _box.put(_lastWeeklySummaryKey, key);
  }

  (int, int)? _parseHourMinute(String value) {
    final match = RegExp(r'^(\d{1,2}):(\d{2})$').firstMatch(value.trim());
    if (match == null) return null;
    final hour = int.tryParse(match.group(1) ?? '');
    final minute = int.tryParse(match.group(2) ?? '');
    if (hour == null || minute == null) return null;
    if (hour < 0 || hour > 23 || minute < 0 || minute > 59) return null;
    return (hour, minute);
  }
}
