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

import '../local/hive_boxes.dart';
import '../local/models/app_settings.dart';
import '../local/models/daily_worship_log.dart';
import 'notification_inbox_service.dart';
import 'notification_runtime_service.dart';
import 'notification_service.dart';

/// Creates in-app inbox events from runtime/system conditions.
class NotificationEventProducerService {
  NotificationEventProducerService._();
  static final NotificationEventProducerService instance =
      NotificationEventProducerService._();

  final NotificationInboxService _inbox = NotificationInboxService.instance;
  final NotificationRuntimeService _runtime =
      NotificationRuntimeService.instance;

  Future<void> emitPermissionWarningsIfNeeded({
    required AppSettings settings,
    required NotificationPermissionStatus permissionStatus,
  }) async {
    if (!settings.adhanEnabled.values.any((v) => v)) return;

    final dateKey = _todayKey();

    if (!permissionStatus.notificationsAllowed) {
      final title = 'Izin notifikasi dinonaktifkan';
      final body =
          'Aktifkan izin notifikasi agar pengingat adzan dan iqamah dapat muncul.';
      if (settings.inboxEnabled) {
        await _inbox.addItem(
          title: title,
          body: body,
          type: 'system',
          source: 'local',
          deeplink: '/settings',
          dedupeKey: 'system.permission.notifications.$dateKey',
          expiresAt: DateTime.now().add(const Duration(days: 2)),
        );
      }
      await _pushSystemIfAllowed(
        settings: settings,
        dedupeSeed: 'push.system.permission.notifications.$dateKey',
        title: title,
        body: body,
      );
    }

    if (!permissionStatus.exactAlarmAllowed) {
      final title = 'Izin alarm presisi belum aktif';
      final body =
          'Aktifkan alarm presisi agar pengingat adzan tepat waktu di perangkat Android.';
      if (settings.inboxEnabled) {
        await _inbox.addItem(
          title: title,
          body: body,
          type: 'system',
          source: 'local',
          deeplink: '/settings',
          dedupeKey: 'system.permission.exact_alarm.$dateKey',
          expiresAt: DateTime.now().add(const Duration(days: 2)),
        );
      }
      await _pushSystemIfAllowed(
        settings: settings,
        dedupeSeed: 'push.system.permission.exact_alarm.$dateKey',
        title: title,
        body: body,
      );
    }
  }

  Future<void> emitScheduleFallback({
    required AppSettings settings,
    required String cityId,
    required bool locationUnavailable,
  }) async {
    final dateKey = _todayKey();
    final title = locationUnavailable
        ? 'Lokasi belum tersedia'
        : 'Jadwal online terganggu';
    final body = locationUnavailable
        ? 'Lokasi perangkat belum aktif. Aplikasi menggunakan lokasi default sementara.'
        : 'Aplikasi memakai perhitungan lokal sementara. Pastikan internet aktif untuk jadwal paling akurat.';
    final scope = locationUnavailable ? 'loc' : 'net';
    final dedupe = 'system.schedule.fallback.$cityId.$dateKey.$scope';

    if (settings.inboxEnabled) {
      await _inbox.addItem(
        title: title,
        body: body,
        type: 'system',
        source: 'local',
        deeplink: '/imsakiyah',
        dedupeKey: dedupe,
        expiresAt: DateTime.now().add(const Duration(days: 1)),
        meta: <String, dynamic>{
          'cityId': cityId,
          'date': dateKey,
          'scope': scope,
        },
      );
    }
    await _pushSystemIfAllowed(
      settings: settings,
      dedupeSeed: 'push.$dedupe',
      title: title,
      body: body,
    );
  }

  Future<void> emitNotificationSyncFailed({
    required AppSettings settings,
    required String cityId,
  }) async {
    final dateKey = _todayKey();
    final title = 'Sinkronisasi alarm adzan gagal';
    final body =
        'Pengingat adzan belum tersinkron. Coba buka aplikasi lagi atau periksa pengaturan notifikasi.';
    final dedupe = 'system.notification.sync_failed.$cityId.$dateKey';

    if (settings.inboxEnabled) {
      await _inbox.addItem(
        title: title,
        body: body,
        type: 'system',
        source: 'local',
        deeplink: '/settings',
        dedupeKey: dedupe,
        expiresAt: DateTime.now().add(const Duration(days: 1)),
        meta: <String, dynamic>{
          'cityId': cityId,
          'date': dateKey,
        },
      );
    }
    await _pushSystemIfAllowed(
      settings: settings,
      dedupeSeed: 'push.$dedupe',
      title: title,
      body: body,
    );
  }

  Future<void> emitStreakRiskIfNeeded({
    required AppSettings settings,
  }) async {
    if (!settings.inboxEnabled || !settings.streakRiskEnabled) return;
    final now = DateTime.now();
    if (now.hour < 18) return;

    final dateKey = _todayKey();
    final worshipBox = Hive.box<DailyWorshipLog>(HiveBoxes.worshipLogs);
    final log = worshipBox.get(dateKey);
    if (log == null) return;

    final tilawahRisk = log.tilawahLog != null && !log.tilawahLog!.isCompleted;
    final dzikirRisk =
        settings.trackDzikir && log.dzikirLog != null && !log.dzikirLog!.petang;

    if (tilawahRisk) {
      final title = 'Streak Tilawah berisiko terputus';
      const body =
          'Selesaikan target tilawah hari ini untuk menjaga konsistensi.';
      final dedupe = 'streak.tilawah.$dateKey';
      await _inbox.addItem(
        title: title,
        body: body,
        type: 'streak_risk',
        source: 'local',
        deeplink: '/quran',
        dedupeKey: dedupe,
        expiresAt: DateTime(now.year, now.month, now.day, 23, 59),
      );
      await _pushHabitIfAllowed(
        settings: settings,
        dedupeSeed: 'push.$dedupe',
        title: title,
        body: body,
      );
    }

    if (dzikirRisk) {
      final title = 'Dzikir petang belum tercatat';
      const body = 'Lengkapi dzikir petang untuk menjaga streak amalan harian.';
      final dedupe = 'streak.dzikir.$dateKey';
      await _inbox.addItem(
        title: title,
        body: body,
        type: 'streak_risk',
        source: 'local',
        deeplink: '/tools/dzikir',
        dedupeKey: dedupe,
        expiresAt: DateTime(now.year, now.month, now.day, 23, 59),
      );
      await _pushHabitIfAllowed(
        settings: settings,
        dedupeSeed: 'push.$dedupe',
        title: title,
        body: body,
      );
    }
  }

  Future<void> emitWeeklySummaryIfNeeded({
    required AppSettings settings,
  }) async {
    if (!settings.inboxEnabled || !settings.weeklySummaryEnabled) return;

    final now = DateTime.now();
    if (now.weekday != DateTime.monday || now.hour < 6) return;

    final monday = now.subtract(Duration(days: now.weekday - 1));
    final weekKey = DateFormat('yyyy-MM-dd').format(monday);
    if (_runtime.lastWeeklySummaryWeekKey() == weekKey) return;

    final worshipBox = Hive.box<DailyWorshipLog>(HiveBoxes.worshipLogs);
    var completionDays = 0;
    var totalPoints = 0;

    for (int i = 1; i <= 7; i++) {
      final date = now.subtract(Duration(days: i));
      final key = DateFormat('yyyy-MM-dd').format(date);
      final log = worshipBox.get(key);
      if (log == null) continue;
      if (log.completionPercent >= 70) completionDays++;
      totalPoints += log.totalPoints;
    }

    await _inbox.addItem(
      title: 'Ringkasan Ibadah Mingguan',
      body:
          '7 hari terakhir: $completionDays hari konsisten, total $totalPoints poin. Lihat detail laporan.',
      type: 'summary',
      source: 'local',
      deeplink: '/laporan',
      dedupeKey: 'summary.weekly.$weekKey',
      expiresAt: now.add(const Duration(days: 7)),
    );
    await _runtime.setLastWeeklySummaryWeekKey(weekKey);
  }

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

  Future<void> _pushSystemIfAllowed({
    required AppSettings settings,
    required String dedupeSeed,
    required String title,
    required String body,
  }) async {
    await _pushNonPrayer(
      settings: settings,
      dedupeSeed: dedupeSeed,
      title: title,
      body: body,
      payloadType: 'system',
      silent: true,
    );
  }

  Future<void> _pushHabitIfAllowed({
    required AppSettings settings,
    required String dedupeSeed,
    required String title,
    required String body,
  }) async {
    await _pushNonPrayer(
      settings: settings,
      dedupeSeed: dedupeSeed,
      title: title,
      body: body,
      payloadType: 'streak_risk',
      silent: false,
    );
  }

  Future<void> _pushNonPrayer({
    required AppSettings settings,
    required String dedupeSeed,
    required String title,
    required String body,
    required String payloadType,
    required bool silent,
  }) async {
    if (!settings.alertsEnabled) return;
    final notif = NotificationService.instance;
    await notif.showNonPrayerAlert(
      settings: settings,
      id: notif.nonPrayerNotificationId(dedupeSeed),
      title: title,
      body: body,
      payloadType: payloadType,
      silent: silent,
    );
  }
}
