import 'package:get/get.dart';
import 'package:on_field_work/helpers/services/api_service.dart';
import 'package:on_field_work/helpers/services/app_logger.dart';
import 'package:on_field_work/helpers/widgets/my_snackbar.dart';

class AddContactController extends GetxController {
  final RxList<String> categories = <String>[].obs;
  final RxList<String> buckets = <String>[].obs;
  final RxList<String> globalProjects = <String>[].obs;
  final RxList<String> tags = <String>[].obs;

  final RxString selectedCategory = ''.obs;
  final RxList<String> selectedBuckets = <String>[].obs;
  final RxString selectedProject = ''.obs;

  final RxList<String> enteredTags = <String>[].obs;
  final RxList<String> filteredSuggestions = <String>[].obs;
  final RxList<String> organizationNames = <String>[].obs;
  final RxList<String> filteredOrgSuggestions = <String>[].obs;

  final RxMap<String, String> categoriesMap = <String, String>{}.obs;
  final RxMap<String, String> bucketsMap = <String, String>{}.obs;
  final RxMap<String, String> projectsMap = <String, String>{}.obs;
  final RxMap<String, String> tagsMap = <String, String>{}.obs;
  final RxBool isInitialized = false.obs;
  final RxList<String> selectedProjects = <String>[].obs;
  final RxBool isSubmitting = false.obs;

  @override
  void onInit() {
    super.onInit();
    logSafe("AddContactController initialized", level: LogLevel.debug);
    fetchInitialData();
  }

  Future<void> fetchInitialData() async {
    logSafe("Fetching initial dropdown data", level: LogLevel.debug);
    await Future.wait([
      fetchBuckets(),
      fetchGlobalProjects(),
      fetchTags(),
      fetchCategories(),
      fetchOrganizationNames(),
    ]);

    // ✅ Mark initialization as done
    isInitialized.value = true;
  }

  void resetForm() {
    selectedCategory.value = '';
    selectedProject.value = '';
    selectedBuckets.clear();
    enteredTags.clear();
    filteredSuggestions.clear();
    filteredOrgSuggestions.clear();
    selectedProjects.clear();
  }

  Future<void> fetchBuckets() async {
    try {
      final response = await ApiService.getContactBucketList();
      if (response != null && response['data'] is List) {
        final names = <String>[];
        for (var item in response['data']) {
          if (item['name'] != null && item['id'] != null) {
            bucketsMap[item['name']] = item['id'].toString();
            names.add(item['name']);
          }
        }
        buckets.assignAll(names);
        logSafe("Fetched \${names.length} buckets");
      }
    } catch (e) {
      logSafe("Failed to fetch buckets: \$e", level: LogLevel.error);
    }
  }

  Future<void> fetchOrganizationNames() async {
    try {
      final orgs = await ApiService.getOrganizationList();
      organizationNames.assignAll(orgs);
      logSafe("Fetched \${orgs.length} organization names");
    } catch (e) {
      logSafe("Failed to load organization names: \$e", level: LogLevel.error);
    }
  }

  Future<void> submitContact({
    String? id,
    required String name,
    required String organization,
    required List<Map<String, String>> emails,
    required List<Map<String, String>> phones,
    required String address,
    required String description,
    String? designation,
  }) async {
    if (isSubmitting.value) return;
    isSubmitting.value = true;

    final categoryId = categoriesMap[selectedCategory.value];
    final bucketIds = selectedBuckets
        .map((name) => bucketsMap[name])
        .whereType<String>()
        .toList();

    if (bucketIds.isEmpty) {
      showAppSnackbar(
        title: "Missing Buckets",
        message: "Please select at least one bucket.",
        type: SnackbarType.warning,
      );
      isSubmitting.value = false;
      return;
    }

    final projectIds = selectedProjects
        .map((name) => projectsMap[name])
        .whereType<String>()
        .toList();

    if (name.trim().isEmpty) {
      showAppSnackbar(
        title: "Missing Name",
        message: "Please enter the contact name.",
        type: SnackbarType.warning,
      );
      isSubmitting.value = false;
      return;
    }

    if (organization.trim().isEmpty) {
      showAppSnackbar(
        title: "Missing Organization",
        message: "Please enter the organization name.",
        type: SnackbarType.warning,
      );
      isSubmitting.value = false;
      return;
    }

    if (selectedBuckets.isEmpty) {
      showAppSnackbar(
        title: "Missing Bucket",
        message: "Please select at least one bucket.",
        type: SnackbarType.warning,
      );
      isSubmitting.value = false;
      return;
    }

    try {
      final tagObjects = enteredTags.map((tagName) {
        final tagId = tagsMap[tagName];
        return tagId != null
            ? {"id": tagId, "name": tagName}
            : {"name": tagName};
      }).toList();

      final body = {
        if (id != null) "id": id,
        "name": name.trim(),
        "organization": organization.trim(),
        if (selectedCategory.value.isNotEmpty && categoryId != null)
          "contactCategoryId": categoryId,
        if (projectIds.isNotEmpty) "projectIds": projectIds,
        "bucketIds": bucketIds,
        if (enteredTags.isNotEmpty) "tags": tagObjects,
        if (emails.isNotEmpty) "contactEmails": emails,
        if (phones.isNotEmpty) "contactPhones": phones,
        if (address.trim().isNotEmpty) "address": address.trim(),
        if (description.trim().isNotEmpty) "description": description.trim(),
        if (designation != null && designation.trim().isNotEmpty)
          "designation": designation.trim(),
      };

      logSafe("${id != null ? 'Updating' : 'Creating'} contact");

      final response = id != null
          ? await ApiService.updateContact(id, body)
          : await ApiService.createContact(body);

      if (response == true) {
        Get.back(result: true);
        showAppSnackbar(
          title: "Success",
          message: id != null
              ? "Contact updated successfully"
              : "Contact created successfully",
          type: SnackbarType.success,
        );
      } else {
        showAppSnackbar(
          title: "Error",
          message: "Failed to ${id != null ? 'update' : 'create'} contact",
          type: SnackbarType.error,
        );
      }
    } catch (e) {
      logSafe("Submit contact error: $e", level: LogLevel.error);
      showAppSnackbar(
        title: "Error",
        message: "Something went wrong",
        type: SnackbarType.error,
      );
    } finally {
      isSubmitting.value = false;
    }
  }

  void filterOrganizationSuggestions(String query) {
    if (query.trim().isEmpty) {
      filteredOrgSuggestions.clear();
      return;
    }

    final lower = query.toLowerCase();
    filteredOrgSuggestions.assignAll(
      organizationNames
          .where((name) => name.toLowerCase().contains(lower))
          .toList(),
    );
    logSafe("Filtered organization suggestions for: \$query",
        level: LogLevel.debug);
  }

  Future<void> fetchGlobalProjects() async {
    try {
      final response = await ApiService.getGlobalProjects();
      if (response != null) {
        final names = <String>[];
        for (var item in response) {
          final name = item['name']?.toString().trim();
          final id = item['id']?.toString().trim();
          if (name != null && id != null && name.isNotEmpty) {
            projectsMap[name] = id;
            names.add(name);
          }
        }
        globalProjects.assignAll(names);
        logSafe("Fetched \${names.length} global projects");
      }
    } catch (e) {
      logSafe("Failed to fetch global projects: \$e", level: LogLevel.error);
    }
  }

  Future<void> fetchTags() async {
    try {
      final response = await ApiService.getContactTagList();
      if (response != null && response['data'] is List) {
        tags.assignAll(List<String>.from(
          response['data'].map((e) => e['name'] ?? '').where((e) => e != ''),
        ));
        logSafe("Fetched \${tags.length} tags");
      }
    } catch (e) {
      logSafe("Failed to fetch tags: \$e", level: LogLevel.error);
    }
  }

  void filterSuggestions(String query) {
    if (query.trim().isEmpty) {
      filteredSuggestions.clear();
      return;
    }

    final lower = query.toLowerCase();
    filteredSuggestions.assignAll(
      tags
          .where((tag) =>
              tag.toLowerCase().contains(lower) && !enteredTags.contains(tag))
          .toList(),
    );
    logSafe("Filtered tag suggestions for: \$query", level: LogLevel.debug);
  }

  void clearSuggestions() {
    filteredSuggestions.clear();
    logSafe("Cleared tag suggestions", level: LogLevel.debug);
  }

  Future<void> fetchCategories() async {
    try {
      final response = await ApiService.getContactCategoryList();
      if (response != null && response['data'] is List) {
        final names = <String>[];
        for (var item in response['data']) {
          final name = item['name']?.toString().trim();
          final id = item['id']?.toString().trim();
          if (name != null && id != null && name.isNotEmpty) {
            categoriesMap[name] = id;
            names.add(name);
          }
        }
        categories.assignAll(names);
        logSafe("Fetched \${names.length} contact categories");
      }
    } catch (e) {
      logSafe("Failed to fetch categories: \$e", level: LogLevel.error);
    }
  }

  void addEnteredTag(String tag) {
    if (tag.trim().isNotEmpty && !enteredTags.contains(tag.trim())) {
      enteredTags.add(tag.trim());
      logSafe("Added tag: \$tag", level: LogLevel.debug);
    }
  }

  void removeEnteredTag(String tag) {
    enteredTags.remove(tag);
    logSafe("Removed tag: \$tag", level: LogLevel.debug);
  }
}
