import 'dart:convert';
import 'dart:io';

import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:image_picker/image_picker.dart';
import 'package:on_field_work/helpers/services/app_logger.dart';

import 'package:on_field_work/controller/my_controller.dart';
import 'package:on_field_work/controller/task_Planning/daily_task_Planning_controller.dart';
import 'package:on_field_work/helpers/services/api_service.dart';
import 'package:on_field_work/helpers/widgets/my_form_validator.dart';
import 'package:on_field_work/helpers/widgets/my_image_compressor.dart';
import 'package:on_field_work/helpers/widgets/my_snackbar.dart';
import 'package:on_field_work/model/dailyTaskPlanning/work_status_model.dart';
import 'package:on_field_work/helpers/widgets/time_stamp_image_helper.dart';

enum ApiStatus { idle, loading, success, failure }

class ReportTaskActionController extends MyController {
  final RxBool isLoading = false.obs;
  final Rx<ApiStatus> reportStatus = ApiStatus.idle.obs;
  final Rx<ApiStatus> commentStatus = ApiStatus.idle.obs;

  final RxList<File> selectedImages = <File>[].obs;
  final RxList<WorkStatus> workStatus = <WorkStatus>[].obs;
  final RxList<WorkStatus> workStatuses = <WorkStatus>[].obs;

  final RxBool showAddTaskCheckbox = false.obs;
  final RxBool isAddTaskChecked = false.obs;

  final RxBool isLoadingWorkStatus = false.obs;
  final Rxn<Map<String, dynamic>> selectedTask = Rxn<Map<String, dynamic>>();

  final RxString selectedWorkStatusName = ''.obs;
  final RxBool isPickingImage = false.obs;

  final MyFormValidator basicValidator = MyFormValidator();
  final DailyTaskPlanningController taskController =
      Get.put(DailyTaskPlanningController());
  final ImagePicker _picker = ImagePicker();

  final assignedDateController = TextEditingController();
  final workAreaController = TextEditingController();
  final activityController = TextEditingController();
  final teamSizeController = TextEditingController();
  final taskIdController = TextEditingController();
  final assignedController = TextEditingController();
  final completedWorkController = TextEditingController();
  final commentController = TextEditingController();
  final assignedByController = TextEditingController();
  final teamMembersController = TextEditingController();
  final plannedWorkController = TextEditingController();
  final approvedTaskController = TextEditingController();

  List<TextEditingController> get _allControllers => [
        assignedDateController,
        workAreaController,
        activityController,
        teamSizeController,
        taskIdController,
        assignedController,
        completedWorkController,
        commentController,
        assignedByController,
        teamMembersController,
        plannedWorkController,
        approvedTaskController,
      ];

  @override
  void onInit() {
    super.onInit();
    logSafe("Initializing ReportTaskController...");
    _initializeFormFields();
  }

  @override
  void onClose() {
    for (final controller in _allControllers) {
      controller.dispose();
    }
    logSafe("Disposed all text controllers in ReportTaskActionController.");
    super.onClose();
  }

  void _initializeFormFields() {
    basicValidator
      ..addField('assigned_date',
          label: "Assigned Date", controller: assignedDateController)
      ..addField('work_area',
          label: "Work Area", controller: workAreaController)
      ..addField('activity', label: "Activity", controller: activityController)
      ..addField('team_size',
          label: "Team Size", controller: teamSizeController)
      ..addField('task_id', label: "Task Id", controller: taskIdController)
      ..addField('assigned', label: "Assigned", controller: assignedController)
      ..addField('completed_work',
          label: "Completed Work",
          required: true,
          controller: completedWorkController)
      ..addField('comment',
          label: "Comment", required: true, controller: commentController)
      ..addField('assigned_by',
          label: "Assigned By", controller: assignedByController)
      ..addField('team_members',
          label: "Team Members", controller: teamMembersController)
      ..addField('planned_work',
          label: "Planned Work", controller: plannedWorkController)
      ..addField('approved_task',
          label: "Approved Task",
          required: true,
          controller: approvedTaskController);
  }

  Future<bool> approveTask({
    required String projectId,
    required String comment,
    required String reportActionId,
    required String approvedTaskCount,
    List<File>? images,
  }) async {
    logSafe("approveTask() started", sensitive: false);

    if (projectId.isEmpty || reportActionId.isEmpty) {
      _showError("Project ID and Report Action ID are required.");
      logSafe("Missing required projectId or reportActionId",
          level: LogLevel.warning);
      return false;
    }

    final approvedTaskInt = int.tryParse(approvedTaskCount);
    final completedWorkInt = int.tryParse(completedWorkController.text.trim());

    if (approvedTaskInt == null) {
      _showError("Invalid approved task count.");
      logSafe("Invalid approvedTaskCount: $approvedTaskCount",
          level: LogLevel.warning);
      return false;
    }

    if (completedWorkInt != null && approvedTaskInt > completedWorkInt) {
      _showError("Approved task count cannot exceed completed work.");
      logSafe("Validation failed: approved > completed",
          level: LogLevel.warning);
      return false;
    }

    if (comment.trim().isEmpty) {
      _showError("Comment is required.");
      logSafe("Comment field is empty", level: LogLevel.warning);
      return false;
    }

    try {
      reportStatus.value = ApiStatus.loading;
      isLoading.value = true;
      logSafe("Calling _prepareImages() for approval...");
      final imageData = await _prepareImages(images);

      logSafe("Calling ApiService.approveTask()");
      final success = await ApiService.approveTask(
        id: projectId,
        workStatus: reportActionId,
        approvedTask: approvedTaskInt,
        comment: comment,
        images: imageData,
      );

      if (success) {
        logSafe("Task approved successfully");
        _showSuccess("Task approved successfully!");
        await taskController.fetchTaskData(projectId);
        return true;
      } else {
        logSafe("API returned failure on approveTask", level: LogLevel.error);
        _showError("Failed to approve task.");
        return false;
      }
    } catch (e, st) {
      logSafe("Error in approveTask: $e",
          level: LogLevel.error, error: e, stackTrace: st);
      _showError("An error occurred.");
      return false;
    } finally {
      isLoading.value = false;
      Future.delayed(const Duration(milliseconds: 500), () {
        reportStatus.value = ApiStatus.idle;
      });
    }
  }

  Future<void> commentTask({
    required String projectId,
    required String comment,
    List<File>? images,
  }) async {
    logSafe("commentTask() started", sensitive: false);

    if (commentController.text.trim().isEmpty) {
      _showError("Comment is required.");
      logSafe("Comment field is empty", level: LogLevel.warning);
      return;
    }

    try {
      isLoading.value = true;

      logSafe("Calling _prepareImages() for comment...");
      final imageData = await _prepareImages(images);

      logSafe("Calling ApiService.commentTask()");
      final success = await ApiService.commentTask(
        id: projectId,
        comment: commentController.text.trim(),
        images: imageData,
      ).timeout(const Duration(seconds: 30), onTimeout: () {
        throw Exception("Request timed out.");
      });

      if (success) {
        logSafe("Comment added successfully");
        _showSuccess("Task commented successfully!");
        await taskController.fetchTaskData(projectId);
      } else {
        logSafe("API returned failure on commentTask", level: LogLevel.error);
        _showError("Failed to comment task.");
      }
    } catch (e, st) {
      logSafe("Error in commentTask: $e",
          level: LogLevel.error, error: e, stackTrace: st);
      _showError("An error occurred while commenting the task.");
    } finally {
      isLoading.value = false;
    }
  }

  Future<void> fetchWorkStatuses() async {
    logSafe("Fetching work statuses...");
    isLoadingWorkStatus.value = true;

    final response = await ApiService.getWorkStatus();
    if (response != null) {
      final model = WorkStatusResponseModel.fromJson(response);
      workStatus.assignAll(model.data);
      logSafe("Fetched ${model.data.length} work statuses");
    } else {
      logSafe("No work statuses found or API call failed",
          level: LogLevel.warning);
    }

    isLoadingWorkStatus.value = false;
    update(['dashboard_controller']);
  }

  Future<List<Map<String, dynamic>>?> _prepareImages(List<File>? images) async {
    if (images == null || images.isEmpty) {
      logSafe("_prepareImages: No images selected.");
      return null;
    }

    logSafe("_prepareImages: Compressing and encoding images...");
    final results = await Future.wait(images.map((file) async {
      final compressedBytes = await compressImageToUnder100KB(file);
      if (compressedBytes == null) return null;

      return {
        "fileName": file.path.split('/').last,
        "base64Data": base64Encode(compressedBytes),
        "contentType": _getContentTypeFromFileName(file.path),
        "fileSize": compressedBytes.lengthInBytes,
        "description": "Image uploaded for task",
      };
    }));

    logSafe(
        "_prepareImages: Prepared ${results.whereType<Map<String, dynamic>>().length} images.");
    return results.whereType<Map<String, dynamic>>().toList();
  }

  String _getContentTypeFromFileName(String fileName) {
    final ext = fileName.split('.').last.toLowerCase();
    return switch (ext) {
      'jpg' || 'jpeg' => 'image/jpeg',
      'png' => 'image/png',
      'webp' => 'image/webp',
      'gif' => 'image/gif',
      _ => 'application/octet-stream',
    };
  }

  Future<void> pickImages({required bool fromCamera}) async {
    try {
      isPickingImage.value = true; // start loading
      logSafe("Opening image picker...");

      if (fromCamera) {
        final pickedFile = await _picker.pickImage(
          source: ImageSource.camera,
          imageQuality: 75,
        );
        if (pickedFile != null) {
          final timestampedFile = await TimestampImageHelper.addTimestamp(
            imageFile: File(pickedFile.path),
          );
          selectedImages.add(timestampedFile);
          logSafe("Image added from camera with timestamp: ${pickedFile.path}");
        }
      } else {
        final pickedFiles = await _picker.pickMultiImage(imageQuality: 75);
        selectedImages.addAll(pickedFiles.map((xfile) => File(xfile.path)));
        logSafe("${pickedFiles.length} images added from gallery.");
      }
    } catch (e, st) {
      logSafe("Error picking images: $e",
          level: LogLevel.error, stackTrace: st);
    } finally {
      isPickingImage.value = false; // stop loading
    }
  }

  void removeImageAt(int index) {
    if (index >= 0 && index < selectedImages.length) {
      logSafe(
        "Removing image at index $index",
      );
      selectedImages.removeAt(index);
    }
  }

  void _showError(String message) => showAppSnackbar(
      title: "Error", message: message, type: SnackbarType.error);

  void _showSuccess(String message) => showAppSnackbar(
      title: "Success", message: message, type: SnackbarType.success);
}
