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

import 'package:on_field_work/controller/attendance/attendance_screen_controller.dart';
import 'package:on_field_work/controller/task_planning/daily_task_controller.dart';
import 'package:on_field_work/controller/task_Planning/daily_task_Planning_controller.dart';
import 'package:on_field_work/controller/expense/expense_screen_controller.dart';
import 'package:on_field_work/controller/expense/expense_detail_controller.dart';
import 'package:on_field_work/controller/directory/directory_controller.dart';
import 'package:on_field_work/controller/directory/notes_controller.dart';
import 'package:on_field_work/controller/document/user_document_controller.dart';
import 'package:on_field_work/controller/document/document_details_controller.dart';
import 'package:on_field_work/controller/dashboard/dashboard_controller.dart';
import 'package:on_field_work/helpers/utils/permission_constants.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':
        _handleExpenseUpdated(data);
        break;
      case 'attendance_updated':
        _handleAttendanceUpdated(data);
        _handleDashboardUpdate(data); // refresh dashboard attendance
        break;
      case 'dashboard_update':
        _handleDashboardUpdate(data); // full dashboard refresh
        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) {
      /// 🔹 Attendance
      case 'Attendance':
        if (_isAttendanceAction(action)) {
          _handleAttendanceUpdated(data);
          _handleDashboardUpdate(data);
        }
        break;
      case 'Team_Modified':
        _handleDashboardUpdate(data);
        break;

      /// 🔹 Tasks
      case 'Report_Task':
        _handleTaskUpdated(data, isComment: false);
        _handleDashboardUpdate(data);
        break;

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

      case 'Task_Modified':
      case 'WorkArea_Modified':
      case 'Floor_Modified':
      case 'Building_Modified':
        _handleTaskPlanningUpdated(data);
        _handleDashboardUpdate(data);
        break;

      /// 🔹 Expenses
      case 'Expenses_Modified':
        _handleExpenseUpdated(data);
        _handleDashboardUpdate(data);
        break;

      /// 🔹 Documents
      case 'Employee_Document_Modified':
      case 'Project_Document_Modified':
        _handleDocumentModified(data);
        break;

      /// 🔹 Directory / Contacts
      case 'Contact_Modified':
        _handleContactModified(data);
        break;

      case 'Contact_Note_Modified':
        _handleContactNoteModified(data);
        break;

      case 'Bucket_Modified':
        _handleBucketModified(data);
        break;

      case 'Bucket_Assigned':
        _handleBucketAssigned(data);
        break;

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

  /// ---------------------- HANDLERS ----------------------

  static void _handleTaskPlanningUpdated(Map<String, dynamic> data) {
    if (!_isCurrentProject(data)) {
      _logger.i("ℹ️ Ignored task planning update from another project.");
      return;
    }

    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.',
    );
  }

  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) {
    if (!_isCurrentProject(data)) {
      _logger.i("ℹ️ Ignored expense update from another project.");
      return;
    }

    final expenseId = data['ExpenseId'];
    if (expenseId == null) {
      _logger.w("⚠️ Expense update received without ExpenseId: $data");
      return;
    }

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

    _safeControllerUpdate<ExpenseDetailController>(
      onFound: (controller) async {
        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) {
    if (!_isCurrentProject(data)) {
      _logger.i("ℹ️ Ignored attendance update from another project.");
      return;
    }

    _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}) {
    if (!_isCurrentProject(data)) {
      _logger.i("ℹ️ Ignored task update from another project.");
      return;
    }

    _safeControllerUpdate<DailyTaskController>(
      onFound: (controller) => controller.refreshTasksFromNotification(
        projectId: data['ProjectId'],
        taskAllocationId: data['TaskAllocationId'],
      ),
      notFoundMessage: '⚠️ DailyTaskController not found, cannot update.',
      successMessage: '✅ DailyTaskController refreshed from notification.',
    );
  }

  /// ---------------------- DOCUMENT HANDLER ----------------------
  static void _handleDocumentModified(Map<String, dynamic> data) {
    if (!_isCurrentProject(data)) {
      _logger.i("ℹ️ Ignored document update from another project.");
      return;
    }

    String entityTypeId;
    String entityId;
    String? documentId = data['DocumentId'];

    if (data['Keyword'] == 'Employee_Document_Modified') {
      entityTypeId = Permissions.employeeEntity;
      entityId = data['EmployeeId'] ?? '';
    } else if (data['Keyword'] == 'Project_Document_Modified') {
      entityTypeId = Permissions.projectEntity;
      entityId = data['ProjectId'] ?? '';
    } else {
      _logger.w("⚠️ Document update received with unknown keyword: $data");
      return;
    }

    if (entityId.isEmpty) {
      _logger.w("⚠️ Document update missing entityId: $data");
      return;
    }

    _logger.i(
        "🔔 Document notification received: keyword=${data['Keyword']}, entityTypeId=$entityTypeId, entityId=$entityId, documentId=$documentId");

    if (Get.isRegistered<DocumentController>()) {
      _safeControllerUpdate<DocumentController>(
        onFound: (controller) async {
          await controller.fetchDocuments(
            entityTypeId: entityTypeId,
            entityId: entityId,
            reset: true,
          );
        },
        notFoundMessage:
            '⚠️ DocumentController not found, cannot refresh list.',
        successMessage: '✅ DocumentController refreshed from notification.',
      );
    } else {
      _logger.w('⚠️ DocumentController not registered, skipping list refresh.');
    }

    if (documentId != null && Get.isRegistered<DocumentDetailsController>()) {
      _safeControllerUpdate<DocumentDetailsController>(
        onFound: (controller) async {
          await controller.fetchDocumentDetails(documentId);
          _logger.i(
              "✅ DocumentDetailsController refreshed for Document $documentId");
        },
        notFoundMessage:
            'ℹ️ DocumentDetailsController not active, skipping details refresh.',
        successMessage: '✅ DocumentDetailsController checked for refresh.',
      );
    } else if (documentId != null) {
      _logger.w(
          '⚠️ DocumentDetailsController not registered, cannot refresh document details.');
    }
  }

  /// ---------------------- DIRECTORY HANDLERS ----------------------
  static void _handleContactModified(Map<String, dynamic> data) {
    _safeControllerUpdate<DirectoryController>(
      onFound: (controller) {
        controller.fetchContacts();
        final contactId = data['ContactId'];
        if (contactId != null) {
          controller.fetchCommentsForContact(contactId);
        }
      },
      notFoundMessage:
          '⚠️ DirectoryController not found, cannot refresh contacts.',
      successMessage:
          '✅ Directory contacts (and notes if applicable) refreshed from notification.',
    );

    _safeControllerUpdate<NotesController>(
      onFound: (controller) => controller.fetchNotes(),
      notFoundMessage: '⚠️ NotesController not found, cannot refresh notes.',
      successMessage: '✅ Notes refreshed from notification.',
    );
  }

  static void _handleContactNoteModified(Map<String, dynamic> data) {
    _handleContactModified(data);
  }

  static void _handleBucketModified(Map<String, dynamic> data) {
    _safeControllerUpdate<DirectoryController>(
      onFound: (controller) => controller.fetchBuckets(),
      notFoundMessage: '⚠️ DirectoryController not found, cannot refresh.',
      successMessage: '✅ Buckets refreshed from notification.',
    );
  }

  static void _handleBucketAssigned(Map<String, dynamic> data) {
    _safeControllerUpdate<DirectoryController>(
      onFound: (controller) => controller.fetchBuckets(),
      notFoundMessage: '⚠️ DirectoryController not found, cannot refresh.',
      successMessage: '✅ Bucket assignments refreshed from notification.',
    );
  }

  /// ---------------------- DASHBOARD HANDLER ----------------------
  static void _handleDashboardUpdate(Map<String, dynamic> data) {
    if (!_isCurrentProject(data)) {
      _logger.i("ℹ️ Ignored dashboard update from another project.");
      return;
    }

    _safeControllerUpdate<DashboardController>(
      onFound: (controller) async {
        final type = data['type'] ?? '';
        switch (type) {
          case 'attendance_updated':
            await controller.fetchRoleWiseAttendance();
            break;

          case 'task_updated':
            await controller.fetchDashboardTasks(
              projectId: controller.projectController.selectedProjectId.value,
            );
            break;

          case 'project_progress_update':
            await controller.fetchProjectProgress();
            break;

          case 'Employee_Suspend':
            final currentProjectId =
                controller.projectController.selectedProjectId.value;
            final projectIdsString = data['ProjectIds'] ?? '';

            final notificationProjectIds =
                projectIdsString.split(',').map((e) => e.trim()).toList();

            if (notificationProjectIds.contains(currentProjectId)) {
              await controller.fetchDashboardTeams(projectId: currentProjectId);
            }
            break;

          case 'Team_Modified':
            final projectId = data['ProjectId'] ??
                controller.projectController.selectedProjectId.value;
            await controller.fetchDashboardTeams(projectId: projectId);
            break;

          case 'full_dashboard_refresh':
          default:
            await controller.refreshDashboard();
        }
      },
      notFoundMessage: '⚠️ DashboardController not found, cannot refresh.',
      successMessage: '✅ DashboardController refreshed from notification.',
    );
  }

  /// ---------------------- UTILITY ----------------------

  static bool _isCurrentProject(Map<String, dynamic> data) {
    try {
      final dashboard = Get.find<DashboardController>();
      final currentProjectId =
          dashboard.projectController.selectedProjectId.value;
      final notificationProjectId = data['ProjectId']?.toString();

      if (notificationProjectId == null || notificationProjectId.isEmpty) {
        return true; // No project info → allow global refresh
      }

      return notificationProjectId == currentProjectId;
    } catch (e) {
      _logger.w("⚠️ Could not verify project context: $e");
      return true;
    }
  }

  static void _safeControllerUpdate<T>({
    required void Function(T controller) onFound,
    required String notFoundMessage,
    required String successMessage,
  }) {
    if (!Get.isRegistered<T>()) {
      _logger.w(notFoundMessage);
      return;
    }

    try {
      final controller = Get.find<T>();
      onFound(controller);
      _logger.i(successMessage);
    } catch (e) {
      _logger.w('⚠️ Error updating controller: $e');
    }
  }
}
