import 'package:awesome_notifications/awesome_notifications.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';

import '../app/constants/sp_keys.dart';
import '../app/dialog/custom_dialog.dart';
import '../app/data/sp/ix_sp.dart';
import '../app/routes/app_pages.dart';
import '../config/translations/strings_enum.dart';
import 'log/logger.dart';
import 'ntp_time_service.dart';

class AwesomeNotificationsHelper {
  // prevent making instance
  AwesomeNotificationsHelper._();

  static const String TAG = 'AwesomeNotificationsHelper';

  // Notification lib
  static AwesomeNotifications awesomeNotifications = AwesomeNotifications();

  // 标记是否已经请求过权限
  static bool _hasRequestedPermission = false;

  /// initialize local notifications service, create channels and groups
  /// setup notifications button actions handlers
  static init() async {
    try {
      // 初始化通知渠道和组
      await _initNotification();
      // 设置监听
      listenToActionButtons();
      // 检查权限但不立即请求
      bool isAllowed = await checkNotificationPermission();
      if (!isAllowed) {}
    } catch (e) {
      log(TAG, 'Notification initialization failed: $e');
    }
  }

  /// 检查通知权限状态
  static Future<bool> checkNotificationPermission() async {
    return await awesomeNotifications.isNotificationAllowed();
  }

  /// 打开通知权限设置
  static Future<void> showNotificationConfigPage() async {
    return await awesomeNotifications.showNotificationConfigPage();
  }

  /// 请求通知权限（可以被Firebase或其他组件调用）
  static Future<bool> requestNotificationPermission() async {
    // 如果已经请求过权限，先检查当前状态
    if (_hasRequestedPermission) {
      final isAllowed = await checkNotificationPermission();
      if (isAllowed) return true;
    }

    // 请求权限
    final isAllowed = await awesomeNotifications
        .requestPermissionToSendNotifications();
    // 标记已请求过权限
    _hasRequestedPermission = true;

    return isAllowed;
  }

  /// 检查是否应该显示通知权限提醒弹窗
  /// 返回 true 表示应该显示
  static Future<bool> shouldShowPushNoticeDialog() async {
    try {
      // 如果已经开启通知权限，不显示
      final isAllowed = await checkNotificationPermission();
      if (isAllowed) {
        log(TAG, 'Notification already allowed, skip dialog');
        return false;
      }

      // 检查是否超过 pushNoticeTime 分钟
      final appConfig = IXSP.getAppConfig();
      final pushNoticeMinutes = appConfig?.pushNoticeTime ?? 10080; // 默认7天
      final lastNoticeTimeStr =
          IXSP.getString(SPKeys.lastPushNoticeTime) ?? '0';
      final lastNoticeTime = int.tryParse(lastNoticeTimeStr) ?? 0;
      final now = NtpTimeService().getCurrentTimestamp();

      // 第一次（lastNoticeTime == 0）或超过间隔时间
      if (lastNoticeTime == 0) {
        log(TAG, 'First time, should show push notice dialog');
        return true;
      }

      final elapsedMinutes = (now - lastNoticeTime) / (1000 * 60);
      if (elapsedMinutes >= pushNoticeMinutes) {
        log(
          TAG,
          'Push notice time elapsed: ${elapsedMinutes.toStringAsFixed(1)}min >= ${pushNoticeMinutes}min',
        );
        return true;
      }

      log(
        TAG,
        'Push notice skipped: ${elapsedMinutes.toStringAsFixed(1)}min elapsed, '
        'need ${pushNoticeMinutes}min',
      );
      return false;
    } catch (e) {
      log(TAG, 'Error checking push notice: $e');
      return false;
    }
  }

  /// 显示通知权限提醒弹窗
  static Future<void> showPushNoticeDialog() async {
    final shouldShow = await shouldShowPushNoticeDialog();
    if (!shouldShow) return;

    // 记录本次提醒时间
    _saveLastPushNoticeTime();

    CustomDialog.showConfirm(
      title: Strings.enableNotifications.tr,
      message: Strings.enableNotificationsDesc.tr,
      confirmText: Strings.enable.tr,
      cancelText: Strings.notNow.tr,
      icon: Icons.notifications_active_outlined,
      iconColor: Get.theme.primaryColor,
      confirmButtonColor: Get.theme.primaryColor,
      onConfirm: () async {
        Navigator.of(Get.context!).pop();
        await requestNotificationPermission();
      },
      onCancel: () {
        Navigator.of(Get.context!).pop();
      },
    );
  }

  /// 记录上次提醒时间
  static void _saveLastPushNoticeTime() {
    IXSP.setString(
      SPKeys.lastPushNoticeTime,
      NtpTimeService().getCurrentTimestamp().toString(),
    );
  }

  /// when user click on notification or click on button on the notification
  static listenToActionButtons() {
    // Only after at least the action method is set, the notification events are delivered
    awesomeNotifications.setListeners(
      onActionReceivedMethod: NotificationController.onActionReceivedMethod,
      onNotificationCreatedMethod:
          NotificationController.onNotificationCreatedMethod,
      onNotificationDisplayedMethod:
          NotificationController.onNotificationDisplayedMethod,
      onDismissActionReceivedMethod:
          NotificationController.onDismissActionReceivedMethod,
    );
  }

  ///init notifications channels
  static _initNotification() async {
    await awesomeNotifications.initialize(
      'resource://mipmap/launcher_icon', // 添加小图标资源路径,
      [
        NotificationChannel(
          channelGroupKey: NotificationChannels.generalChannelGroupKey,
          channelKey: NotificationChannels.generalChannelKey,
          channelName: NotificationChannels.generalChannelName,
          groupKey: NotificationChannels.generalGroupKey,
          channelDescription: NotificationChannels.generalChannelDescription,
          defaultColor: Colors.green,
          ledColor: Colors.white,
          channelShowBadge: true,
          playSound: true,
          importance: NotificationImportance.Max,
        ),
        NotificationChannel(
          channelGroupKey: NotificationChannels.chatChannelGroupKey,
          channelKey: NotificationChannels.chatChannelKey,
          channelName: NotificationChannels.chatChannelName,
          groupKey: NotificationChannels.chatGroupKey,
          channelDescription: NotificationChannels.chatChannelDescription,
          defaultColor: Colors.green,
          ledColor: Colors.white,
          channelShowBadge: true,
          playSound: true,
          importance: NotificationImportance.Max,
        ),
      ],
      channelGroups: [
        NotificationChannelGroup(
          channelGroupKey: NotificationChannels.generalChannelGroupKey,
          channelGroupName: NotificationChannels.generalChannelGroupName,
        ),
        NotificationChannelGroup(
          channelGroupKey: NotificationChannels.chatChannelGroupKey,
          channelGroupName: NotificationChannels.chatChannelGroupName,
        ),
      ],
    );
  }

  //display notification for user with sound
  static Future<bool> showNotification({
    required String title,
    required String body,
    required int id,
    String? channelKey,
    String? groupKey,
    NotificationLayout? notificationLayout,
    String? summary,
    List<NotificationActionButton>? actionButtons,
    Map<String, String>? payload,
    String? largeIcon,
  }) async {
    try {
      final isAllowed = await checkNotificationPermission();
      if (!isAllowed) {
        final requested = await requestNotificationPermission();
        if (!requested) return false;
      }

      await awesomeNotifications.createNotification(
        content: NotificationContent(
          id: id,
          title: title,
          body: body,
          groupKey: groupKey ?? NotificationChannels.generalGroupKey,
          channelKey: channelKey ?? NotificationChannels.generalChannelKey,
          showWhen: true,
          payload: payload,
          notificationLayout: notificationLayout ?? NotificationLayout.Default,
          autoDismissible: true,
          summary: summary,
          largeIcon: largeIcon,
        ),
        actionButtons: actionButtons,
      );
      return true;
    } catch (e) {
      log(TAG, 'Sending notification failed: $e');
      return false;
    }
  }
}

class NotificationController {
  /// Use this method to detect when a new notification or a schedule is created
  @pragma("vm:entry-point")
  static Future<void> onNotificationCreatedMethod(
    ReceivedNotification receivedNotification,
  ) async {
    // Your code goes here
  }

  /// Use this method to detect every time that a new notification is displayed
  @pragma("vm:entry-point")
  static Future<void> onNotificationDisplayedMethod(
    ReceivedNotification receivedNotification,
  ) async {
    // Your code goes here
  }

  /// Use this method to detect if the user dismissed a notification
  @pragma("vm:entry-point")
  static Future<void> onDismissActionReceivedMethod(
    ReceivedAction receivedAction,
  ) async {
    // Your code goes here
  }

  /// Use this method to detect when the user taps on a notification or action button
  @pragma("vm:entry-point")
  static Future<void> onActionReceivedMethod(
    ReceivedAction receivedAction,
  ) async {
    try {
      final payload = receivedAction.payload;
      if (payload != null) {
        final route = payload['route'];
        if (route != null) {
          Get.key.currentState?.pushNamed(route);
        } else {
          Get.key.currentState?.pushNamed(Routes.HOME);
        }
      }
    } catch (e) {
      log(
        "onActionReceivedMethod",
        'Handling notification click event failed: $e',
      );
    }
  }
}

class NotificationChannels {
  // chat channel (for messages only)
  static String get chatChannelKey => "chat_channel";
  static String get chatChannelName => "Chat Notifications";
  static String get chatGroupKey => "chat_group_key";
  static String get chatChannelGroupKey => "chat_channel_group";
  static String get chatChannelGroupName => "Chat Notifications";
  static String get chatChannelDescription =>
      "Receive chat and message notifications";

  // general channel (for all other notifications)
  static String get generalChannelKey => "general_channel";
  static String get generalGroupKey => "general_group_key";
  static String get generalChannelGroupKey => "general_channel_group";
  static String get generalChannelGroupName => "General Notifications";
  static String get generalChannelName => "General Notifications";
  static String get generalChannelDescription =>
      "Receive general app notifications";
}
