import 'package:get/get.dart';
import 'package:logger/logger.dart';

import 'package:marco/controller/attendance/attendance_screen_controller.dart';
import 'package:marco/controller/task_planning/daily_task_controller.dart';
import 'package:marco/controller/task_Planning/daily_task_Planning_controller.dart';
import 'package:marco/controller/expense/expense_screen_controller.dart';
import 'package:marco/controller/expense/expense_detail_controller.dart';

/// Handles incoming FCM notification actions and updates UI/controllers.
class NotificationActionHandler {
  static final Logger _logger = Logger();

  /// Main entry point — call this for any notification `data` map.
  static void handle(Map<String, dynamic> data) {
    _logger.i('📲 Handling notification action: $data');

    if (data.isEmpty) {
      _logger.w('⚠️ Empty notification data received.');
      return;
    }

    final type = data['type'];
    final action = data['Action'];
    final keyword = data['Keyword'];

    if (type != null) {
      _handleByType(type, data);
    } else if (keyword != null) {
      _handleByKeyword(keyword, action, data);
    } else {
      _logger.w('⚠️ Unhandled notification: $data');
    }
  }

  /// Handle notification if identified by `type`
  static void _handleByType(String type, Map<String, dynamic> data) {
    switch (type) {
      case 'expense_updated':
        // No specific handler yet
        break;
      case 'attendance_updated':
        _handleAttendanceUpdated(data);
        break;
      default:
        _logger.w('⚠️ Unknown notification type: $type');
    }
  }

  /// Handle notification if identified by `keyword`
  static void _handleByKeyword(
      String keyword, String? action, Map<String, dynamic> data) {
    switch (keyword) {
      case 'Attendance':
        if (_isAttendanceAction(action)) {
          _handleAttendanceUpdated(data);
        }
        break;

      case 'Report_Task':
        _handleTaskUpdated(data, isComment: false);
        break;

      case 'Task_Comment':
        _handleTaskUpdated(data, isComment: true);
        break;
      case 'Expenses_Modified':
        _handleExpenseUpdated(data);
        break;

      // ✅ New cases
      case 'Task_Modified':
      case 'WorkArea_Modified':
      case 'Floor_Modified':
      case 'Building_Modified':
        _handleTaskPlanningUpdated(data);
        break;

      default:
        _logger.w('⚠️ Unhandled notification keyword: $keyword');
    }
  }

  static void _handleTaskPlanningUpdated(Map<String, dynamic> data) {
    final projectId = data['ProjectId'];
    if (projectId == null) {
      _logger.w("⚠️ TaskPlanning update received without ProjectId: $data");
      return;
    }

    _safeControllerUpdate<DailyTaskPlanningController>(
      onFound: (controller) {
        controller.fetchTaskData(projectId);
      },
      notFoundMessage:
          '⚠️ DailyTaskPlanningController not found, cannot refresh.',
      successMessage:
          '✅ DailyTaskPlanningController refreshed from notification.',
    );
  }

  /// Validates the set of allowed Attendance actions
  static bool _isAttendanceAction(String? action) {
    const validActions = {
      'CHECK_IN',
      'CHECK_OUT',
      'REQUEST_REGULARIZE',
      'REQUEST_DELETE',
      'REGULARIZE',
      'REGULARIZE_REJECT'
    };
    return validActions.contains(action);
  }

  static void _handleExpenseUpdated(Map<String, dynamic> data) {
    final expenseId = data['ExpenseId'];
    if (expenseId == null) {
      _logger.w("⚠️ Expense update received without ExpenseId: $data");
      return;
    }

    // Update Expense List
    _safeControllerUpdate<ExpenseController>(
      onFound: (controller) async {
        await controller.fetchExpenses();
      },
      notFoundMessage: '⚠️ ExpenseController not found, cannot refresh list.',
      successMessage:
          '✅ ExpenseController refreshed from expense notification.',
    );

    // Update Expense Detail (if open and matches this expenseId)
    _safeControllerUpdate<ExpenseDetailController>(
      onFound: (controller) async {
        // only refresh if the open screen is for this expense
        if (controller.expense.value?.id == expenseId) {
          await controller.fetchExpenseDetails();
          _logger
              .i("✅ ExpenseDetailController refreshed for Expense $expenseId");
        }
      },
      notFoundMessage: 'ℹ️ ExpenseDetailController not active, skipping.',
      successMessage: '✅ ExpenseDetailController checked for refresh.',
    );
  }

  static void _handleAttendanceUpdated(Map<String, dynamic> data) {
    _safeControllerUpdate<AttendanceController>(
      onFound: (controller) => controller.refreshDataFromNotification(
        projectId: data['ProjectId'],
      ),
      notFoundMessage: '⚠️ AttendanceController not found, cannot update.',
      successMessage: '✅ AttendanceController refreshed from notification.',
    );
  }

  static void _handleTaskUpdated(Map<String, dynamic> data,
      {required bool isComment}) {
    _safeControllerUpdate<DailyTaskController>(
      onFound: (controller) => controller.refreshTasksFromNotification(
        projectId: data['ProjectId'],
        taskAllocationId: data['TaskAllocationId'],
      ),
      notFoundMessage: '⚠️ DailyTaskController not found, cannot update.',
      successMessage: '✅ DailyTaskController refreshed from notification.',
    );
  }

  /// Generic reusable method for safe GetX controller access + log handling
  static void _safeControllerUpdate<T>({
    required void Function(T controller) onFound,
    required String notFoundMessage,
    required String successMessage,
  }) {
    try {
      final controller = Get.find<T>();
      onFound(controller);
      _logger.i(successMessage);
    } catch (e) {
      _logger.w(notFoundMessage);
    }
  }
}
