import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:on_field_work/helpers/services/app_logger.dart';
import 'package:on_field_work/helpers/services/api_service.dart';
import 'package:on_field_work/model/document/master_document_type_model.dart';
import 'package:on_field_work/model/document/master_document_tags.dart';
import 'package:on_field_work/helpers/widgets/my_snackbar.dart';

class DocumentUploadController extends GetxController {
  // Observables
  var isLoading = false.obs;
  var isUploading = false.obs;

  var categories = <DocumentType>[].obs;
  var tags = <TagItem>[].obs;

  DocumentType? selectedCategory;

  /// --- FILE HANDLING ---
  String? selectedFileName;
  String? selectedFileBase64;
  String? selectedFileContentType;
  int? selectedFileSize;

  /// --- TAG HANDLING ---
  final tagCtrl = TextEditingController();
  final enteredTags = <String>[].obs;
  final filteredSuggestions = <String>[].obs;
  var documentTypes = <DocumentType>[].obs;
  DocumentType? selectedType;
  @override
  void onInit() {
    super.onInit();
    fetchCategories();
    fetchTags();
  }

  /// Fetch available document categories
  Future<void> fetchCategories() async {
    try {
      isLoading.value = true;
      final response = await ApiService.getMasterDocumentTypesApi();
      if (response != null && response.data.isNotEmpty) {
        categories.assignAll(response.data);
        logSafe("Fetched categories: ${categories.length}");
      } else {
        logSafe("No categories fetched", level: LogLevel.warning);
      }
    } finally {
      isLoading.value = false;
    }
  }

  Future<void> fetchDocumentTypes(String categoryId) async {
    try {
      isLoading.value = true;
      final response =
          await ApiService.getDocumentTypesByCategoryApi(categoryId);
      if (response != null && response.data.isNotEmpty) {
        documentTypes.assignAll(response.data);
        selectedType = null; // reset previous type
      } else {
        documentTypes.clear();
        selectedType = null;
      }
    } finally {
      isLoading.value = false;
    }
  }

  Future<String?> fetchPresignedUrl(String versionId) async {
    return await ApiService.getPresignedUrlApi(versionId);
  }

  /// Fetch available document tags
  Future<void> fetchTags() async {
    try {
      isLoading.value = true;
      final response = await ApiService.getMasterDocumentTagsApi();
      if (response != null) {
        tags.assignAll(response.data);
        logSafe("Fetched tags: ${tags.length}");
      } else {
        logSafe("No tags fetched", level: LogLevel.warning);
      }
    } finally {
      isLoading.value = false;
    }
  }

  /// --- TAG LOGIC ---
  void filterSuggestions(String query) {
    if (query.isEmpty) {
      filteredSuggestions.clear();
      return;
    }
    filteredSuggestions.assignAll(
      tags.map((t) => t.name).where(
            (tag) => tag.toLowerCase().contains(query.toLowerCase()),
          ),
    );
  }

  void addEnteredTag(String tag) {
    if (tag.trim().isEmpty) return;
    if (!enteredTags.contains(tag.trim())) {
      enteredTags.add(tag.trim());
    }
  }

  void removeEnteredTag(String tag) {
    enteredTags.remove(tag);
  }

  void clearSuggestions() {
    filteredSuggestions.clear();
  }

  /// Upload document
  Future<bool> uploadDocument({
    required String documentId,
    required String name,
    required String entityId,
    required String documentTypeId,
    required String fileName,
    required String base64Data,
    required String contentType,
    required int fileSize,
    String? description,
  }) async {
    try {
      isUploading.value = true;

      final payloadTags =
          enteredTags.map((t) => {"name": t, "isActive": true}).toList();

      final payload = {
        "documentId": documentId,
        "name": name,
        "description": description,
        "entityId": entityId,
        "documentTypeId": documentTypeId,
        "fileName": fileName,
        "base64Data":
            base64Data.isNotEmpty ? "<base64-string-truncated>" : null,
        "contentType": contentType,
        "fileSize": fileSize,
        "tags": payloadTags,
      };

      // Log the payload (hide long base64 string for readability)
      logSafe("Upload payload: $payload");

      final success = await ApiService.uploadDocumentApi(
        documentId: documentId,
        name: name,
        description: description,
        entityId: entityId,
        documentTypeId: documentTypeId,
        fileName: fileName,
        base64Data: base64Data,
        contentType: contentType,
        fileSize: fileSize,
        tags: payloadTags,
      );

      if (success) {
        showAppSnackbar(
          title: "Success",
          message: "Document uploaded successfully",
          type: SnackbarType.success,
        );
      } else {
        showAppSnackbar(
          title: "Error",
          message: "Could not upload document",
          type: SnackbarType.error,
        );
      }

      return success;
    } catch (e, stack) {
      logSafe("Upload error: $e", level: LogLevel.error);
      logSafe("Stacktrace: $stack", level: LogLevel.debug);
      showAppSnackbar(
        title: "Error",
        message: "An unexpected error occurred",
        type: SnackbarType.error,
      );
      return false;
    } finally {
      isUploading.value = false;
    }
  }

  Future<bool> editDocument(Map<String, dynamic> payload) async {
    try {
      isUploading.value = true;

      final attachment = payload["attachment"];

      final success = await ApiService.editDocumentApi(
        id: payload["id"],
        name: payload["name"],
        documentId: payload["documentId"],
        description: payload["description"],
        tags: (payload["tags"] as List).cast<Map<String, dynamic>>(),
        attachment: attachment, 
      );

      if (success) {
        showAppSnackbar(
          title: "Success",
          message: "Document updated successfully",
          type: SnackbarType.success,
        );
      } else {
        showAppSnackbar(
          title: "Error",
          message: "Failed to update document",
          type: SnackbarType.error,
        );
      }

      return success;
    } catch (e, stack) {
      logSafe("Edit error: $e", level: LogLevel.error);
      logSafe("Stacktrace: $stack", level: LogLevel.debug);
      showAppSnackbar(
        title: "Error",
        message: "An unexpected error occurred",
        type: SnackbarType.error,
      );
      return false;
    } finally {
      isUploading.value = false;
    }
  }
}
