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

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:rasadyar_core/core.dart';
import 'package:rasadyar_livestock/data/model/response/address/address.dart';
import 'package:rasadyar_livestock/data/model/response/live_tmp/livestock_model.dart';
import 'package:rasadyar_livestock/data/repository/livestock/livestock_repository.dart';
import 'package:rasadyar_livestock/data/service/live_stock_storage_service.dart';
import 'package:rasadyar_livestock/injection/live_stock_di.dart';

class RequestTaggingLogic extends GetxController {
  LiveStockStorageService liveStockStorageService = Get.find<LiveStockStorageService>();
  RxInt currentIndex = 0.obs;
  final int maxStep = 2;

  RxBool nextButtonEnabled = true.obs;

  LivestockRepository livestockRepository = diLiveStock.get<LivestockRepository>();
  LivestockData? liveStockTmp;

  //region First Step
  final TextEditingController phoneController = TextEditingController();
  final TextEditingController fullNameController = TextEditingController();
  final TextEditingController addressController = TextEditingController();
  ImagePicker imagePicker = diLiveStock.get<ImagePicker>();
  Rxn<XFile> rancherImage = Rxn<XFile>(null);

  //endregion

  //region Second Step
  Rxn<XFile> herdImage = Rxn<XFile>(null);
  Rx<Resource<LocationDetails>> addressDetails = Rx<Resource<LocationDetails>>(Resource.loading());
  RxnString addressDetailsValue = RxnString(null);
  Rxn<LatLng> addressLocationValue = Rxn<LatLng>();

  RxInt selectedSegment = 0.obs;
  RxBool searchIsSelected = false.obs;
  RxBool filterIsSelected = false.obs;
  RxList<int> filterSelected = <int>[].obs;
  RxList isExpandedList = <int>[].obs;

  RxBool tst1 = false.obs;

  //endregion

  //region Third Step
  RxnString species = RxnString(null);
  RxnString breed = RxnString(null);
  Rx<Jalali> dateOfBirth = Rx<Jalali>(Jalali.now());
  RxInt selectedSex = 0.obs;
  TextEditingController motherTagNumberController = TextEditingController();
  TextEditingController fatherTagNumberController = TextEditingController();
  TextEditingController herdTagController = TextEditingController();
  RxnString tagType = RxnString();
  Rxn<XFile> taggingImage = Rxn<XFile>(null);

  Rxn<Rancher> rancher = Rxn<Rancher>(null);
  Rxn<Herd> herd = Rxn<Herd>(null);
  RxList<Livestock> livestockList = <Livestock>[].obs;

  RxBool isLoading = false.obs;

  //endregion

  @override
  void onInit() {
    super.onInit();
    setUpTextControllerListeners();
    setUpNextButtonListeners();
    ever(rancherImage, (callback) {
      setUpNextButtonListeners();
    });

    determineCurrentPosition();
  }

  @override
  void onReady() {
    super.onReady();

    rancher.value = Rancher(
      name: 'حسن حسنی',
      phone: '09121234567',
      image: '/9j/4nd9KcTTcWUsuoF0cSwuZSjYX',
    );

    herd.value = Herd(
      location: Location(lat: 35.825081, lng: 50.948177),
      address: 'استان البرز, بخش مرکزی کرج, کرج, منطقه ۵, دهقان ویلا, بلوار سرداران',
      image: '/9j/4QL6RXhpZgAATU0AKgAA',
    );

    var s = List.generate(
      10_000,
      (index) => Livestock(
        sex: index % 2 == 0 ? 'نر' : 'ماده',
        tagNumber: index.toString(),
        fatherTag: (index * 2).toString(),
        motherTag: (index * 3).toString(),
        species: 'نوع $index',
        breed: index % 2 == 0 ? 'گوسفند ماده' : 'گاو ماده',
        tagType: index % 2 == 0 ? 'نوع 1' : 'نوع 2',
        dateOfBirth: "23/10/2023",
        image: '/9j/4QLmRXhpZgAATU',
      ),
    );
    livestockList.addAll(s);
  }

  @override
  void onClose() {
    super.onClose();
  }

  void onNext() async {
    if (currentIndex.value < maxStep) {
      if (currentIndex.value == 0) {
        liveStockTmp = LivestockData(
          rancher: Rancher(
            name: fullNameController.text,
            phone: phoneController.text,
            image: await convertToBase64(rancherImage),
          ),
        );
      } else if (currentIndex.value == 1) {
        liveStockTmp = liveStockTmp?.copyWith(
          herd: Herd(
            location: Location(
              lat: addressLocationValue.value?.latitude,
              lng: addressLocationValue.value?.longitude,
            ),
            address: addressDetailsValue.value,
            image: await convertToBase64(herdImage),
          ),
        );
      }
      currentIndex.value++;
    } else {
      createTaggingLiveStock();
    }
  }

  void onPrevious() {
    if (currentIndex.value > 0) {
      currentIndex.value--;
    }
  }

  void setUpNextButtonListeners() {
    if (currentIndex.value == 0) {
      /* nextButtonEnabled.value =
          phoneController.text.isNotEmpty &&
          fullNameController.text.isNotEmpty &&
          addressController.text.isNotEmpty &&
          rancherImage.value != null;*/

      return;
    }
  }

  void setUpTextControllerListeners() {
    phoneController.addListener(setUpNextButtonListeners);
    fullNameController.addListener(setUpNextButtonListeners);
    addressController.addListener(setUpNextButtonListeners);
  }

  Future<void> pickImage(Rxn<XFile> file) async {
    file.value = await imagePicker.pickImage(
      source: ImageSource.camera,
      imageQuality: 60,
      maxWidth: 1080,
      maxHeight: 720,
    );

    getFileSizeInKB(file.value?.path ?? '', tag: 'Picked');
  }

  Future<void> cropImage() async {
    if (rancherImage.value == null) return;

    final CroppedFile? cropped = await ImageCropper().cropImage(
      sourcePath: rancherImage.value!.path,
      maxWidth: 1080,
      maxHeight: 720,
      compressQuality: 60,
    );
    if (cropped == null) return;
    rancherImage.value = XFile(cropped.path);

    getFileSizeInKB(rancherImage.value?.path ?? '', tag: 'Cropped');
  }

  Future<String?> convertToBase64(Rxn<XFile> fromFile) async {
    if (fromFile.value == null) return null;

    final bytes = await fromFile.value!.readAsBytes();
    final base64String = base64Encode(bytes);

    return base64String;
  }

  Future<void> convertBase64ToImage(RxnString fromFile, Rxn<XFile> toFile) async {
    if (fromFile.value == null) return;

    // Decode Base64 → bytes
    Uint8List imageBytes = base64Decode(fromFile.value!);

    // Save bytes to a temp file
    final tempDir = await getTemporaryDirectory();
    final filePath = '${tempDir.path}/temp_image.png';
    await File(filePath).writeAsBytes(imageBytes);

    // Create XFile from that temp file
    toFile.value = XFile(filePath);
  }

  Future<void> determineCurrentPosition() async {
    final position = await Geolocator.getCurrentPosition(
      locationSettings: AndroidSettings(accuracy: LocationAccuracy.best),
    );

    getLocationDetails(position.latitude, position.longitude);
  }

  Future<void> getLocationDetails(double latitude, double longitude) async {
    safeCall(
      call: () => livestockRepository.getLocationDetails(latitude: latitude, longitude: longitude),
      onSuccess: (result) {
        if (result != null) {
          addressDetails.value = Resource.success(result);
          buildAddressDetails(result);
          addressLocationValue.value = LatLng(latitude, longitude);
        } else {
          addressDetails.value = Resource.error('Failed to fetch address');
        }
      },
      onError: (error, stackTrace) {
        addressDetails.value = Resource.error('Error fetching address: ${error.toString()}');
      },
    );
  }

  void buildAddressDetails(LocationDetails result) {
    final address = result.address;
    if (address != null) {
      final addressParts = [
        address.state,
        address.county,
        address.district,
        address.city,
        address.suburb,
        address.neighbourhood,
        address.road,
      ].where((part) => part != null && part.isNotEmpty).join(', ');
      addressDetailsValue.value = addressParts;
    } else {
      addressDetailsValue.value = 'Address not found';
    }
  }

  void clearForms() {
    phoneController.clear();
    fullNameController.clear();
    addressController.clear();
    rancherImage.value = null;
    herdImage.value = null;
    addressDetails.value = Resource.loading();
    addressDetailsValue.value = null;
    addressLocationValue.value = null;
    species.value = null;
    breed.value = null;
    selectedSex.value = 0;
    motherTagNumberController.clear();
    fatherTagNumberController.clear();
    herdTagController.clear();
    tagType.value = null;
    taggingImage.value = null;
  }

  Future<void> createTaggingLiveStock() async {
    // isLoading.value = true;
    if (livestockList.isEmpty) {
      Get.snackbar('Error', 'Please fill all required fields');
      return;
    }

    var batches = chunkedList(
      livestockList,
      500,
    ).map((e) => LivestockData(rancher: rancher.value, herd: herd.value, livestock: e));

    await liveStockStorageService.saveBulkLiveStockData(batches);

    var tmpData = await liveStockStorageService.getLiveStockData();

    for (int i = 0; i < tmpData.length; i++) {
      await safeCall(
        call: () => livestockRepository.createTaggingLiveStock(data: tmpData[i]),
        onSuccess: (result) async {
          if (i == tmpData.length - 1) {
            Get.snackbar('Success', 'All livestock tagged successfully');
            await liveStockStorageService.deleteLiveBox();
            var ss = await liveStockStorageService.getLiveStockData();
            iLog('tagged livestock: ${ss.length}');
          }
        },
        onError: (error, stackTrace) {},
      );
    }

    isLoading.value = false;
  }

  List<List<Livestock>> chunkedList(List<Livestock> list, int chunkSize) {
    List<List<Livestock>> batches = [];

    for (int i = 0; i < livestockList.length; i += chunkSize) {
      batches.add(livestockList.sublist(i, min(i + chunkSize, livestockList.length)));
    }
    return batches;
  }

  void addLiveStock() async {
    livestockList.add(
      Livestock(
        species: species.value,
        dateOfBirth: dateOfBirth.value.formatCompactDate(),
        breed: breed.value,
        sex: selectedSegment.value == 0 ? 'نر' : 'ماده',
        motherTag: motherTagNumberController.text,
        fatherTag: fatherTagNumberController.text,
        tagNumber: herdTagController.text,
        tagType: tagType.value,
        image: await convertToBase64(taggingImage),
      ),
    );

    clearForms();

    iLog(livestockList);
  }
}
