import 'package:flutter/material.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:timezone/timezone.dart' as tz;
import 'package:timezone/data/latest.dart' as tz_data;

import '../models/event_model.dart';

class NotificationService {
  static NotificationService _instance = NotificationService._internal();
  factory NotificationService() => _instance;
  
  // 생성자에서 플러그인을 주입받을 수 있도록 변경
  NotificationService._internal([FlutterLocalNotificationsPlugin? plugin])
      : _notificationsPlugin = plugin ?? FlutterLocalNotificationsPlugin();
  
  // 테스트용 인스턴스 설정 메서드
  static void setTestInstance(NotificationService instance) {
    _instance = instance;
  }
  
  // 테스트용 인스턴스 생성 포함한 새 메서드
  @visibleForTesting
  static NotificationService createTestInstance(FlutterLocalNotificationsPlugin mockPlugin) {
    return NotificationService._internal(mockPlugin);
  }

  final FlutterLocalNotificationsPlugin _notificationsPlugin;
  bool _isInitialized = false;

  // 알림 서비스 초기화
  Future<void> initialize() async {
    if (_isInitialized) return;

    // 타임존 초기화
    tz_data.initializeTimeZones();

    // 안드로이드 설정
    const AndroidInitializationSettings androidSettings = AndroidInitializationSettings('@mipmap/ic_launcher');
    
    // iOS 설정
    const DarwinInitializationSettings iOSSettings = DarwinInitializationSettings(
      requestAlertPermission: true,
      requestBadgePermission: true,
      requestSoundPermission: true,
    );
    
    // 초기화 설정
    const InitializationSettings initSettings = InitializationSettings(
      android: androidSettings,
      iOS: iOSSettings,
    );
    
    // 알림 플러그인 초기화
    await _notificationsPlugin.initialize(
      initSettings,
      onDidReceiveNotificationResponse: (NotificationResponse response) {
        // 알림 클릭 시 처리
        debugPrint('알림 클릭: ${response.payload}');
      },
    );

    _isInitialized = true;
    debugPrint('알림 서비스 초기화 완료');
  }

  // 권한 요청
  Future<bool> requestPermission() async {
    if (!_isInitialized) await initialize();
    
    // iOS에서 권한 요청
    final bool? result = await _notificationsPlugin
        .resolvePlatformSpecificImplementation<IOSFlutterLocalNotificationsPlugin>()
        ?.requestPermissions(
          alert: true,
          badge: true,
          sound: true,
        );
    
    return result ?? false;
  }

  // 즉시 알림 표시
  Future<void> showNotification({
    required int id,
    required String title,
    required String body,
    String? payload,
  }) async {
    if (!_isInitialized) await initialize();

    const AndroidNotificationDetails androidDetails = AndroidNotificationDetails(
      'event_channel',
      '이벤트 알림',
      channelDescription: '이벤트 관련 알림을 표시합니다',
      importance: Importance.high,
      priority: Priority.high,
      showWhen: true,
    );

    const DarwinNotificationDetails iOSDetails = DarwinNotificationDetails(
      presentAlert: true,
      presentBadge: true,
      presentSound: true,
    );

    const NotificationDetails notificationDetails = NotificationDetails(
      android: androidDetails,
      iOS: iOSDetails,
    );

    await _notificationsPlugin.show(
      id,
      title,
      body,
      notificationDetails,
      payload: payload,
    );
  }

  // 예약 알림 설정
  Future<void> scheduleNotification({
    required int id,
    required String title,
    required String body,
    required DateTime scheduledDate,
    String? payload,
  }) async {
    if (!_isInitialized) await initialize();

    final tz.TZDateTime scheduledTZDate = tz.TZDateTime.from(
      scheduledDate,
      tz.local,
    );

    const AndroidNotificationDetails androidDetails = AndroidNotificationDetails(
      'event_reminder_channel',
      '이벤트 리마인더',
      channelDescription: '예정된 이벤트에 대한 알림을 표시합니다',
      importance: Importance.high,
      priority: Priority.high,
    );

    const DarwinNotificationDetails iOSDetails = DarwinNotificationDetails(
      presentAlert: true,
      presentBadge: true,
      presentSound: true,
    );

    const NotificationDetails notificationDetails = NotificationDetails(
      android: androidDetails,
      iOS: iOSDetails,
    );

    await _notificationsPlugin.zonedSchedule(
      id,
      title,
      body,
      scheduledTZDate,
      notificationDetails,
      androidScheduleMode: AndroidScheduleMode.exactAllowWhileIdle,
      matchDateTimeComponents: DateTimeComponents.time,
      payload: payload,
    );
  }

  // 이벤트 시작 알림 설정
  Future<void> scheduleEventStartReminder(Event event) async {
    if (event.id.isEmpty) return;
    
    // 이벤트 시작 1시간 전 알림
    final DateTime reminderTime = event.startDate.subtract(const Duration(hours: 1));
    
    // 현재 시간이 알림 시간보다 이후라면 알림을 설정하지 않음
    if (reminderTime.isBefore(DateTime.now())) return;
    
    await scheduleNotification(
      id: event.id.hashCode,
      title: '이벤트 시작 알림',
      body: '${event.title} 이벤트가 1시간 후에 시작됩니다.',
      scheduledDate: reminderTime,
      payload: event.id,
    );
  }

  // 이벤트 등록 마감 알림 설정
  Future<void> scheduleRegistrationDeadlineReminder(Event event) async {
    if (event.id.isEmpty || event.registrationDeadline == null) return;
    
    // 등록 마감 1일 전 알림
    final DateTime reminderTime = event.registrationDeadline!.subtract(const Duration(days: 1));
    
    // 현재 시간이 알림 시간보다 이후라면 알림을 설정하지 않음
    if (reminderTime.isBefore(DateTime.now())) return;
    
    await scheduleNotification(
      id: event.id.hashCode + 1, // 이벤트 시작 알림과 ID가 겹치지 않도록 함
      title: '이벤트 등록 마감 알림',
      body: '${event.title} 이벤트의 등록이 내일 마감됩니다.',
      scheduledDate: reminderTime,
      payload: event.id,
    );
  }

  // 특정 이벤트의 모든 알림 취소
  Future<void> cancelEventNotifications(String eventId) async {
    await _notificationsPlugin.cancel(eventId.hashCode);
    await _notificationsPlugin.cancel(eventId.hashCode + 1);
  }

  // 모든 알림 취소
  Future<void> cancelAllNotifications() async {
    await _notificationsPlugin.cancelAll();
  }
}
