import 'package:get/get.dart';
import 'package:on_field_work/helpers/services/api_service.dart';
import 'package:on_field_work/model/service_project/service_projects_details_model.dart';
import 'package:on_field_work/model/service_project/job_list_model.dart';
import 'package:on_field_work/model/service_project/service_project_job_detail_model.dart';
import 'package:geolocator/geolocator.dart';
import 'package:on_field_work/model/service_project/job_attendance_logs_model.dart';
import 'package:on_field_work/model/service_project/job_allocation_model.dart';
import 'package:on_field_work/model/service_project/job_status_response.dart';
import 'package:on_field_work/model/service_project/job_comments.dart';
import 'dart:convert';
import 'dart:io';
import 'package:mime/mime.dart';
import 'package:image_picker/image_picker.dart';

class ServiceProjectDetailsController extends GetxController {
  // -------------------- Observables --------------------
  var projectId = ''.obs;
  var projectDetail = Rxn<ProjectDetail>();
  var jobList = <JobEntity>[].obs;
  var jobDetail = Rxn<JobDetailsResponse>();
  var showArchivedJobs = false.obs; // true = archived, false = active

  // Loading states
  var isLoading = false.obs;
  var isJobLoading = false.obs;
  var isJobDetailLoading = false.obs;

  // Error messages
  var errorMessage = ''.obs;
  var jobErrorMessage = ''.obs;
  var jobDetailErrorMessage = ''.obs;
  final ImagePicker picker = ImagePicker();
  var isProcessingAttachment = false.obs; 

  // Pagination
  var pageNumber = 1;
  final int pageSize = 20;
  var hasMoreJobs = true.obs;

  var isTagging = false.obs;
  var attendanceMessage = ''.obs;
  var attendanceLog = Rxn<JobAttendanceResponse>();
  var teamList = <ServiceProjectAllocation>[].obs;
  var isTeamLoading = false.obs;
  var teamErrorMessage = ''.obs;
  var filteredJobList = <JobEntity>[].obs;
// -------------------- Job Status --------------------
// With this:
  var jobStatusList = <JobStatus>[].obs;
  var selectedJobStatus = Rx<JobStatus?>(null);
  var isJobStatusLoading = false.obs;
  var jobStatusErrorMessage = ''.obs;
// -------------------- Job Comments --------------------
  var jobComments = <CommentItem>[].obs;
  var isCommentsLoading = false.obs;
  var commentsErrorMessage = ''.obs;
  // -------------------- Lifecycle --------------------
  @override
  void onInit() {
    super.onInit();
    fetchProjectJobs();
    filteredJobList.value = jobList;
  }

  // -------------------- Project --------------------
  void setProjectId(String id) {
    if (projectId.value == id) return;
    projectId.value = id;

    // Reset pagination and list
    pageNumber = 1;
    hasMoreJobs.value = true;
    jobList.clear();
    filteredJobList.clear();

    // Fetch project detail
    fetchProjectDetail();

    // Always fetch jobs for this project
    fetchProjectJobs(refresh: true);
  }

  void updateJobSearch(String searchText) {
    if (searchText.isEmpty) {
      filteredJobList.value = jobList;
    } else {
      filteredJobList.value = jobList.where((job) {
        final lowerSearch = searchText.toLowerCase();
        return job.title.toLowerCase().contains(lowerSearch) ||
            (job.description.toLowerCase().contains(lowerSearch)) ||
            (job.tags?.any(
                    (tag) => tag.name.toLowerCase().contains(lowerSearch)) ??
                false);
      }).toList();
    }
  }

  Future<void> fetchProjectTeams() async {
    if (projectId.value.isEmpty) {
      teamErrorMessage.value = "Invalid project ID";
      return;
    }

    isTeamLoading.value = true;
    teamErrorMessage.value = '';

    try {
      final result = await ApiService.getServiceProjectAllocationList(
        projectId: projectId.value,
        isActive: true,
      );

      if (result != null) {
        teamList.value = result;
      } else {
        teamErrorMessage.value = "No teams found";
      }
    } catch (e) {
      teamErrorMessage.value = "Error fetching teams: $e";
    } finally {
      isTeamLoading.value = false;
    }
  }

  Future<void> fetchJobStatus({required String statusId}) async {
    if (projectId.value.isEmpty) {
      jobStatusErrorMessage.value = "Invalid project ID";
      return;
    }

    isJobStatusLoading.value = true;
    jobStatusErrorMessage.value = '';

    try {
      final statuses = await ApiService.getMasterJobStatus(
        projectId: projectId.value,
        statusId: statusId,
      );

      if (statuses != null && statuses.isNotEmpty) {
        jobStatusList.value = statuses;

        // Keep previously selected if exists, else pick first
        selectedJobStatus.value = statuses.firstWhere(
          (status) => status.id == selectedJobStatus.value?.id,
          orElse: () => statuses.first,
        );

        print("Job Status List: ${jobStatusList.map((e) => e.name).toList()}");
      } else {
        jobStatusErrorMessage.value = "No job statuses found";
      }
    } catch (e) {
      jobStatusErrorMessage.value = "Error fetching job status: $e";
    } finally {
      isJobStatusLoading.value = false;
    }
  }

  Future<void> fetchProjectDetail() async {
    if (projectId.value.isEmpty) {
      errorMessage.value = "Invalid project ID";
      return;
    }

    isLoading.value = true;
    errorMessage.value = '';

    try {
      final result =
          await ApiService.getServiceProjectDetailApi(projectId.value);

      if (result != null && result.data != null) {
        projectDetail.value = result.data!;
      } else {
        errorMessage.value =
            result?.message ?? "Failed to fetch project details";
      }
    } catch (e) {
      errorMessage.value = "Error: $e";
    } finally {
      isLoading.value = false;
    }
  }

  Future<void> fetchJobAttendanceLog(String attendanceId) async {
    if (attendanceId.isEmpty) {
      attendanceMessage.value = "Invalid attendance ID";
      return;
    }

    isJobDetailLoading.value = true;
    attendanceMessage.value = '';

    try {
      final result =
          await ApiService.getJobAttendanceLog(attendanceId: attendanceId);

      if (result != null) {
        attendanceLog.value = result;
      } else {
        attendanceMessage.value = "Attendance log not found or empty";
      }
    } catch (e) {
      attendanceMessage.value = "Error fetching attendance log: $e";
    } finally {
      isJobDetailLoading.value = false;
    }
  }

  // -------------------- Job List (modified to always load) --------------------
  Future<void> fetchProjectJobs({bool refresh = false}) async {
    if (projectId.value.isEmpty) return;

    if (refresh) pageNumber = 1;
    if (!hasMoreJobs.value && !refresh) return;

    isJobLoading.value = true;
    jobErrorMessage.value = '';

    try {
      final result = await ApiService.getServiceProjectJobListApi(
        projectId: projectId.value,
        pageNumber: pageNumber,
        pageSize: pageSize,
        isActive: true,
        isArchive: showArchivedJobs.value,
      );

      if (result != null && result.data != null) {
        final newJobs = result.data?.data ?? [];

        if (refresh || pageNumber == 1) {
          jobList.value = newJobs;
        } else {
          jobList.addAll(newJobs);
        }

        filteredJobList.value = jobList;

        hasMoreJobs.value = newJobs.length == pageSize;
        if (hasMoreJobs.value) pageNumber++;
      } else {
        jobErrorMessage.value = result?.message ?? "Failed to fetch jobs";
      }
    } catch (e) {
      jobErrorMessage.value = "Error fetching jobs: $e";
    } finally {
      isJobLoading.value = false;
    }
  }

  Future<void> fetchMoreJobs() async => fetchProjectJobs();

  // -------------------- Manual Refresh --------------------
  Future<void> refresh() async {
    pageNumber = 1;
    hasMoreJobs.value = true;

    await Future.wait([
      fetchProjectDetail(),
      fetchProjectJobs(),
    ]);
  }

  // -------------------- Job Detail --------------------
  Future<void> fetchJobDetail(String jobId) async {
    if (jobId.isEmpty) {
      jobDetailErrorMessage.value = "Invalid job ID";
      return;
    }

    isJobDetailLoading.value = true;
    jobDetailErrorMessage.value = '';

    try {
      final result = await ApiService.getServiceProjectJobDetailApi(jobId);
      if (result != null) {
        jobDetail.value = result;
      } else {
        jobDetailErrorMessage.value = "Failed to fetch job details";
      }
    } catch (e) {
      jobDetailErrorMessage.value = "Error fetching job details: $e";
    } finally {
      isJobDetailLoading.value = false;
    }
  }

  Future<Position?> _getCurrentLocation() async {
    try {
      bool serviceEnabled = await Geolocator.isLocationServiceEnabled();
      if (!serviceEnabled) {
        attendanceMessage.value = "Location services are disabled.";
        return null;
      }

      LocationPermission permission = await Geolocator.checkPermission();
      if (permission == LocationPermission.denied) {
        permission = await Geolocator.requestPermission();
        if (permission == LocationPermission.denied) {
          attendanceMessage.value = "Location permission denied";
          return null;
        }
      }

      if (permission == LocationPermission.deniedForever) {
        attendanceMessage.value =
            "Location permission permanently denied. Enable it from settings.";
        return null;
      }

      return await Geolocator.getCurrentPosition(
          desiredAccuracy: LocationAccuracy.high);
    } catch (e) {
      attendanceMessage.value = "Failed to get location: $e";
      return null;
    }
  }

  Future<void> fetchJobComments({bool refresh = false}) async {
    if (jobDetail.value?.data?.id == null) {
      commentsErrorMessage.value = "Invalid job ID";
      return;
    }

    if (refresh) pageNumber = 1;

    isCommentsLoading.value = true;
    commentsErrorMessage.value = '';

    try {
      final response = await ApiService.getJobCommentList(
        jobTicketId: jobDetail.value!.data!.id!,
        pageNumber: pageNumber,
        pageSize: pageSize,
      );

      if (response != null && response.data != null) {
        final newComments = response.data?.data ?? [];

        if (refresh || pageNumber == 1) {
          jobComments.value = newComments;
        } else {
          jobComments.addAll(newComments);
        }

        hasMoreJobs.value =
            (response.data?.totalEntities ?? 0) > (pageNumber * pageSize);
        if (hasMoreJobs.value) pageNumber++;
      } else {
        commentsErrorMessage.value =
            response?.message ?? "Failed to fetch comments";
      }
    } catch (e) {
      commentsErrorMessage.value = "Error fetching comments: $e";
    } finally {
      isCommentsLoading.value = false;
    }
  }

  Future<bool> addJobComment({
    required String jobId,
    required String comment,
    List<File>? files,
  }) async {
    try {
      List<Map<String, dynamic>> attachments = [];

      if (files != null && files.isNotEmpty) {
        for (final file in files) {
          final bytes = await file.readAsBytes();
          final base64Data = base64Encode(bytes);
          final mimeType =
              lookupMimeType(file.path) ?? "application/octet-stream";

          attachments.add({
            "fileName": file.path.split('/').last,
            "base64Data": base64Data,
            "contentType": mimeType,
            "fileSize": bytes.length,
            "description": "",
            "isActive": true,
          });
        }
      }

      final success = await ApiService.addJobComment(
        jobTicketId: jobId,
        comment: comment,
        attachments: attachments,
      );

      if (success) {
        await fetchJobDetail(jobId);
        refresh();
      }

      return success;
    } catch (e) {
      print("Error adding comment: $e");
      return false;
    }
  }

  /// Tag In / Tag Out for a job with proper payload
  Future<void> updateJobAttendance({
    required String jobId,
    required int action,
    String comment = "Updated via app",
    File? attachment,
  }) async {
    if (jobId.isEmpty) return;

    isTagging.value = true;
    attendanceMessage.value = '';

    try {
      final position = await _getCurrentLocation();
      if (position == null) {
        isTagging.value = false;
        return;
      }

      Map<String, dynamic>? attachmentPayload;

      if (attachment != null) {
        final bytes = await attachment.readAsBytes();
        final base64Data = base64Encode(bytes);
        final mimeType =
            lookupMimeType(attachment.path) ?? 'application/octet-stream';
        attachmentPayload = {
          "documentId": jobId,
          "fileName": attachment.path.split('/').last,
          "base64Data": base64Data,
          "contentType": mimeType,
          "fileSize": bytes.length,
          "description": "Attached via app",
          "isActive": true,
        };
      }

      final payload = {
        "jobTcketId": jobId,
        "action": action,
        "latitude": position.latitude.toString(),
        "longitude": position.longitude.toString(),
        "comment": comment,
        "attachment": attachmentPayload,
      };

      final success = await ApiService.updateServiceProjectJobAttendance(
        payload: payload,
      );

      if (success) {
        attendanceMessage.value =
            action == 0 ? "Tagged In successfully" : "Tagged Out successfully";
        await fetchJobDetail(jobId);
      } else {
        attendanceMessage.value = "Failed to update attendance";
      }
    } catch (e) {
      attendanceMessage.value = "Error updating attendance: $e";
    } finally {
      isTagging.value = false;
    }
  }

  // ------------------------------------------------------------
  // 🔥 AUTO REFRESH JOB LIST AFTER ADDING A JOB
  // ------------------------------------------------------------
  Future<void> refreshJobsAfterAdd() async {
    pageNumber = 1;
    hasMoreJobs.value = true;
    await fetchProjectJobs();
  }
}
