// notification_view_model.dart
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:tm_app/core/utils/app_toast.dart';
import 'package:tm_app/core/utils/result.dart';
import 'package:tm_app/data/repositories/notification_repository.dart';
import 'package:tm_app/data/services/model/notification__response/notification_response_model.dart';
import 'package:tm_app/view_models/home_view_model.dart';
import 'package:tm_app/views/notification/strings/notification_strings.dart';

class NotificationViewModel with ChangeNotifier {
  final NotificationsRepository _repository;

  NotificationViewModel({required NotificationsRepository repositoryViewModel})
    : _repository = repositoryViewModel {
    WidgetsBinding.instance.addPostFrameCallback((_) {
      init();
    });
  }

  void init() async {
    clearData();
    await getNotifications();
    await getUnreadNotifications();
    await getImportantNotifications();
  }

  void clearData() {
    allNotificationResponse = null;
    unreadNotificationResponse = null;
    importantNotificationResponse = null;
    _errorMessage = null;
    currentPageAll = 1;
    totalPagesAll = 0;
    currentPageUnread = 1;
    totalPagesUnread = 0;
    currentPageImportant = 1;
    totalPagesImportant = 0;

    notifyListeners();
  }

  static const int _pageSize = 10;

  String? _errorMessage;
  String? get errorMessage => _errorMessage;

  // All
  NotificationResponseModel? allNotificationResponse;
  bool isLoadingAll = false;
  bool isMoreLoadingAll = false;
  bool hasMoreAll = true;
  int currentPageAll = 1;
  int totalPagesAll = 0;

  // Unread
  NotificationResponseModel? unreadNotificationResponse;
  bool isLoadingUnread = false;
  bool isMoreLoadingUnread = false;
  bool hasMoreUnread = true;
  int currentPageUnread = 1;
  int totalPagesUnread = 0;

  // Important
  NotificationResponseModel? importantNotificationResponse;
  bool isLoadingImportant = false;
  bool isMoreLoadingImportant = false;
  bool hasMoreImportant = true;
  int currentPageImportant = 1;
  int totalPagesImportant = 0;

  Future<void> getNotifications({
    int page = 1,
    bool isPagination = false,
  }) async {
    if (isPagination) {
      isMoreLoadingAll = true;
    } else {
      isLoadingAll = true;
    }
    notifyListeners();

    final int offset = (page - 1) * _pageSize;
    final result = await _repository.getNotifications(
      limit: _pageSize,
      offset: offset,
    );

    switch (result) {
      case Ok<NotificationResponseModel>():
        final data = result.value;
        if (isPagination && allNotificationResponse != null) {
          final old = allNotificationResponse?.data ?? [];
          final fresh = data.data ?? [];
          allNotificationResponse = data.copyWith(data: [...old, ...fresh]);
        } else {
          allNotificationResponse = data;
        }

        _updateImportantFromAll();

        currentPageAll = page;
        totalPagesAll = data.meta?.pages ?? 1;
        hasMoreAll = (data.data?.length ?? 0) >= _pageSize;
        break;

      case Error<NotificationResponseModel>():
        _errorMessage = result.error.toString();
        break;
    }

    isLoadingAll = false;
    isMoreLoadingAll = false;
    notifyListeners();
  }

  Future<void> getUnreadNotifications({
    int page = 1,
    bool isPagination = false,
  }) async {
    if (isPagination) {
      isMoreLoadingUnread = true;
    } else {
      isLoadingUnread = true;
    }
    notifyListeners();

    final int offset = (page - 1) * _pageSize;
    final result = await _repository.getUnreadNotifications(
      limit: _pageSize,
      offset: offset,
    );

    switch (result) {
      case Ok<NotificationResponseModel>():
        final data = result.value;
        if (isPagination && unreadNotificationResponse != null) {
          final old = unreadNotificationResponse?.data ?? [];
          final fresh = data.data ?? [];
          unreadNotificationResponse = data.copyWith(data: [...old, ...fresh]);
        } else {
          unreadNotificationResponse = data;
        }

        currentPageUnread = page;
        totalPagesUnread = data.meta?.pages ?? 1;
        hasMoreUnread = (data.data?.length ?? 0) >= _pageSize;
        break;

      case Error<NotificationResponseModel>():
        _errorMessage = result.error.toString();
        break;
    }

    isLoadingUnread = false;
    isMoreLoadingUnread = false;
    notifyListeners();
  }

  Future<void> getImportantNotifications({
    int page = 1,
    bool isPagination = false,
  }) async {
    if (isPagination) {
      isMoreLoadingImportant = true;
    } else {
      isLoadingImportant = true;
    }
    notifyListeners();

    final int offset = (page - 1) * _pageSize;

    final result = await _repository.getImportantNotifications(
      limit: _pageSize,
      offset: offset,
    );

    switch (result) {
      case Ok<NotificationResponseModel>():
        final data = result.value;
        if (isPagination && importantNotificationResponse != null) {
          final old = importantNotificationResponse?.data ?? [];
          final fresh = data.data ?? [];
          importantNotificationResponse = data.copyWith(
            data: [...old, ...fresh],
          );
        } else {
          importantNotificationResponse = data;
        }

        currentPageImportant = page;
        totalPagesImportant = data.meta?.pages ?? 1;
        hasMoreImportant = (data.data?.length ?? 0) >= _pageSize;
        break;

      case Error<NotificationResponseModel>():
        _errorMessage = result.error.toString();

        _updateImportantFromAll();
        break;
    }

    isLoadingImportant = false;
    isMoreLoadingImportant = false;
    notifyListeners();
  }

  void _updateImportantFromAll() {
    final all = allNotificationResponse?.data ?? [];
    final filtered =
        (all.where((n) {
          final p = n.priority ?? '';
          return p.toLowerCase() == 'important';
        }).toList());

    if (allNotificationResponse != null) {
      importantNotificationResponse = allNotificationResponse!.copyWith(
        data: filtered,
      );
    } else {
      importantNotificationResponse = null;
    }
  }

  Future<void> jumpToPageAll(int page) async {
    if (totalPagesAll == 0 || page < 1 || page > totalPagesAll) {
      return;
    }
    await getNotifications(page: page);
  }

  Future<void> jumpToPageUnread(int page) async {
    if (totalPagesUnread == 0 || page < 1 || page > totalPagesUnread) {
      return;
    }
    await getUnreadNotifications(page: page);
  }

  Future<void> jumpToPageImportant(int page) async {
    if (totalPagesImportant == 0 || page < 1 || page > totalPagesImportant) {
      return;
    }
    await getImportantNotifications(page: page);
  }

  Future<void> markAllAsRead(BuildContext context) async {
    isLoadingAll = true;
    _errorMessage = null;
    notifyListeners();

    final result = await _repository.markAllAsRead();

    if (!context.mounted) {
      return;
    }

    switch (result) {
      case Ok<Map<String, dynamic>>():
        final response = result.value;
        final success = response['success'] as bool? ?? false;
        final message =
            response['message'] as String? ??
            NotificationStrings.unknownResponse;

        if (success) {
          if (allNotificationResponse?.data != null) {
            final updatedNotifications =
                allNotificationResponse!.data!
                    .map((n) => n.copyWith(seen: true))
                    .toList();

            allNotificationResponse = allNotificationResponse!.copyWith(
              data: updatedNotifications,
            );

            unreadNotificationResponse = unreadNotificationResponse?.copyWith(
              data: [],
            );

            if (importantNotificationResponse?.data != null) {
              final updatedImportant =
                  importantNotificationResponse!.data!
                      .map((n) => n.copyWith(seen: true))
                      .toList();

              importantNotificationResponse = importantNotificationResponse!
                  .copyWith(data: updatedImportant);
            }
          }

          if (context.mounted) {
            AppToast.success(
              context,
              NotificationStrings.allNotificationMarkedAsRead,
            );
          }
          final homeViewModel = context.read<HomeViewModel>();
          homeViewModel.serUnreadNotificationFalse();
        } else {
          _errorMessage = message;
          if (context.mounted) {
            AppToast.error(context, message);
          }
        }
        break;

      case Error<Map<String, dynamic>>():
        _errorMessage = result.error.toString();
        if (context.mounted) {
          AppToast.error(context, _errorMessage!);
        }
        break;
    }

    isLoadingAll = false;
    notifyListeners();
  }

  String timeAgo(timestamp) {
    final int ts = int.tryParse(timestamp.toString()) ?? 0;
    final createdAt = DateTime.fromMillisecondsSinceEpoch(ts * 1000).toLocal();
    final now = DateTime.now();
    final difference = now.difference(createdAt);

    if (difference.inMinutes < 1) {
      return NotificationStrings.now;
    } else if (difference.inMinutes < 60) {
      return '${difference.inMinutes} ${NotificationStrings.min}';
    } else if (difference.inHours < 24) {
      return '${difference.inHours} ${NotificationStrings.hour}';
    } else if (difference.inDays == 1) {
      return NotificationStrings.yesterday;
    } else {
      return '${difference.inDays} ${NotificationStrings.daysAgo}';
    }
  }
}
