import 'dart:async';
import 'dart:convert';
import 'dart:math';

import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:geolocator/geolocator.dart' as LocationAccuracy;
import 'package:flutter/cupertino.dart';
import 'package:geocoding/geocoding.dart';
import 'package:geolocator/geolocator.dart';
import 'package:get/get.dart';
import 'package:http/http.dart' as http;
import 'package:minio/io.dart';
import 'package:minio/minio.dart';
import 'package:path/path.dart' as path;
import 'package:image_picker/image_picker.dart';
import 'package:intl/intl.dart';
import 'dart:io';
import 'package:rounded_loading_button_plus/rounded_loading_button.dart';
import 'package:shared_preferences/shared_preferences.dart';
import '../../Data/Provider/Appcategory/Appcategoryprovider.dart';
import '../../Data/Repository/Appcategory/Appcategoryrepository.dart';
import '../../Data/Repository/Applocation/Applocationrepository.dart';
import '../../Data/Repository/Authentication/Createtenantuser/Createtenantuserrepository.dart';
import '../../Data/Repository/TenantPartner/Tenantpartnerrepository.dart';
import '../../Helper/Logger.dart';
import '../../Helper/location_service.dart';
import '../../Helper/toast.dart';
import '../../Model/Request/Authentication/Createuser/Createuserresponse.dart';
import '../../Model/Response/Appcategory/app_category_response.dart';
import '../../Model/Response/Applocations/Applocationresponse.dart';
import '../../Model/Response/Authentication/Createtenantuser/Createtenantuserresponse.dart';
import '../../Model/Response/Partners/Getpartnerinforequest.dart';
import '../../View/Success/Successview.dart';

class CreateUserController extends GetxController {
  String appLocationName = '';
  String appCategoryName = '';
  String partnerName = '';
  String? latitude;
  String? longitude;
  String? catName;
  int? moduleIdByCategory = 0;
  String? subCatName;
  String? fcmEntryToken;

  String? todayDate;
  String? validityDate;
  String? url; // This will hold the uploaded image URL

  int selectedIndex = 0;
  int? catId;
  int? subCatId;

  String? deviceId;

  int appLocationId = 0;
  int partnerSelectedIndex = -1;
  int? partnerId;

  List<AppLocationDetails> locations = [];
  List<PartnerInfoDetails> getPartners = [];
  List<AppCategoryDetails> appCategory = [];

  Position? resultPosition;

  List<SubCategory> subCategories = [];

  Future<void> getFcmToken() async {
    try {
      await FirebaseMessaging.instance.requestPermission();

      fcmEntryToken = await FirebaseMessaging.instance.getToken();
      print('FCM Token: $fcmEntryToken');

      FirebaseMessaging.instance.onTokenRefresh.listen((newToken) {
        fcmEntryToken = newToken;
        print('FCM Token Refreshed: $fcmEntryToken');
      });
    } catch (e) {
      print('Error getting FCM token: $e');
    }
  }

  Future<void> getSubCategories() async {
    final provider = SubCategoryProvider();
    final List<SubCategory> fetched = await provider.fetchSubCategories();
    subCategories.assignAll(fetched);
    update();
  }

  final String apiUrl = "https://fiesta.nearle.app/live/api/v1/mob/utils/getsubcategories";

  Future<GetSubCategoriesResponse?> fetchSubCategories() async {
    try {
      final response = await http.get(Uri.parse(apiUrl));
      if (response.statusCode == 200) {
        final jsonData = json.decode(response.body);
        return GetSubCategoriesResponse.fromJson(jsonData);
      } else {
        print("Failed to load subcategories: ${response.statusCode}");
      }
    } catch (e) {
      print("Error fetching subcategories: $e");
    }
    return null;
  }

  bool shimmer = true;
  bool categoryShimmer = true;
  bool isEnterAddress = false;
  String selectedCategoryName = '';
  var currentLat;
  var currentLong;

  TextEditingController firstnameController = TextEditingController();
  TextEditingController lastnameController = TextEditingController();
  TextEditingController companyNameController = TextEditingController();
  TextEditingController emailController = TextEditingController();
  TextEditingController gstinNumberController = TextEditingController();
  TextEditingController contactNoController = TextEditingController();
  TextEditingController addressController = TextEditingController();
  TextEditingController stateController = TextEditingController();
  TextEditingController cityController = TextEditingController();
  TextEditingController suburbController = TextEditingController();
  TextEditingController postcodeController = TextEditingController();

  final searchText = ''.obs;
  final predictions = <Map<String, dynamic>>[].obs;
  final selectedPlace = {}.obs;

  final RoundedLoadingButtonController btnController = RoundedLoadingButtonController();

  AppLocationRepository appLocationRepository = AppLocationRepository();
  GetPartnersRepository getPartnersRepository = GetPartnersRepository();
  AppCategoryRepository appCategoryRepository = AppCategoryRepository();
  CreateTenantUserRepository createTenantUserRepository = CreateTenantUserRepository();

  final GooglePlacesService placesService = GooglePlacesService();

  getAppLocations() async {
    GetAppLocations? result = await appLocationRepository.getAppLocations();
    if (result?.code == 200) {
      locations = result?.details ?? [];
      shimmer = false;
      update();
    } else {
      Toast.showToast("${result?.message}");
    }
  }

  getCurrentLocation() async {
    resultPosition = await Geolocator.getCurrentPosition(
        desiredAccuracy: LocationAccuracy.LocationAccuracy.high);
    currentLat = resultPosition?.latitude.toString();
    currentLong = resultPosition?.longitude.toString();
    print('currentLatinlocation $currentLat');
    print('currentLonglocation $currentLong');
    getAddressFromLatLongs(double.parse(currentLat), double.parse(currentLong));
  }

  getAppCategory() async {
    categoryShimmer = true;
    update();

    try {
      final provider = SubCategoryProvider();
      final List<SubCategory> subCats = await provider.fetchSubCategories();

      final Map<int, AppCategoryDetails> uniqueCats = {};

      for (var sub in subCats) {
        if (sub.categoryid != null && sub.catgeoryname != null) {
          uniqueCats[sub.categoryid!] = AppCategoryDetails(
            categoryid: sub.categoryid,
            categoryname: sub.catgeoryname,
            moduleid: sub.moduleid,
          );
        }
      }

      appCategory = uniqueCats.values.toList();
      logger.i('Loaded ${appCategory.length} categories');

      if (appCategory.isNotEmpty) {
        catId = appCategory[0].categoryid;
        catName = appCategory[0].categoryname;
        moduleIdByCategory = appCategory[0].moduleid;
      }
    } catch (e) {
      logger.e('Error loading categories: $e');
      Toast.showToast("Failed to load categories");
    }

    categoryShimmer = false;
    update();
  }

  Future<void> getAddressFromLatLongs(double latitudes, double longitudes) async {
    await placemarkFromCoordinates(latitudes, longitudes).then((List<Placemark> placemarks) {
      Placemark place = placemarks[0];
      cityController.text = place.locality ?? '';
      stateController.text = place.administrativeArea ?? '';
      suburbController.text = '${place.subLocality ?? place.street}';
      postcodeController.text = place.postalCode ?? '';
      latitude = latitudes.toString();
      longitude = longitudes.toString();
      addressController.text =
      '${place.street}, ${place.subLocality}, ${place.locality}, ${place.administrativeArea} ${place.subAdministrativeArea}, ${place.country}, ${place.postalCode}.';
      update();
    }).catchError((e) {
      debugPrint(e);
    });
  }

  getPartnersInfo(locationId) async {
    GetPartnersInfo? result = await getPartnersRepository.getPartners(locationId);
    getPartners = result?.details ?? [];
    partnerId = getPartners.isNotEmpty ? getPartners[0].partnerid : null;
    print('getPartnerslengthss${getPartners.length}');
    print('getpartnerId$partnerId');
  }

  onSearchTextChanged(String text) async {
    searchText.value = text;
    if (text.length > 2) {
      try {
        final places = await placesService.getPlacesPredictions(text);
        predictions.assignAll(places);
        update();
      } catch (e) {
        print('Error fetching predictions: $e');
      }
    } else {
      predictions.clear();
      update();
    }
  }

  getPlaceDetails(String placeId, locationAddress) async {
    try {
      final details = await placesService.getPlaceDetails(placeId);
      selectedPlace.value = details;
      getAddressFromLatLng(
        selectedPlace['geometry']['location']['lat'],
        selectedPlace['geometry']['location']['lng'],
        locationAddress,
      );
    } catch (e) {
      print('Error fetching place details: $e');
    }
  }

  getAddressFromLatLng(double latitudes, double longitudes, locationAddress) async {
    await placemarkFromCoordinates(latitudes, longitudes).then((List<Placemark> placemarks) {
      Placemark place = placemarks[0];
      cityController.text = place.locality ?? '';
      stateController.text = place.administrativeArea ?? '';
      suburbController.text = (place.subLocality?.isNotEmpty == true) ? place.subLocality! : place.street!;
      postcodeController.text = place.postalCode ?? '';
      addressController.text = locationAddress;
      latitude = latitudes.toString();
      longitude = longitudes.toString();
      predictions.clear();
      update();
    }).catchError((e) {
      debugPrint(e);
    });
  }

  void doSomething() async {
    Timer(const Duration(seconds: 1), () {
      profileValidation();
    });
  }

  profileValidation() async {
    if (firstnameController.text.isEmpty) {
      btnController.reset();
      Toast.showToast("Please Enter Firstname");
      return;
    }
    if (companyNameController.text.isEmpty) {
      btnController.reset();
      Toast.showToast("Please Enter Companyname");
      return;
    }
    if (emailController.text.isEmpty) {
      btnController.reset();
      Toast.showToast("Please Enter Email");
      return;
    }
    if (addressController.text.isEmpty) {
      btnController.reset();
      Toast.showToast("Please Enter Address");
      return;
    }
    if (suburbController.text.isEmpty) {
      btnController.reset();
      Toast.showToast("Please Enter Suburb");
      return;
    }
    if (cityController.text.isEmpty) {
      btnController.reset();
      Toast.showToast("Please Enter City");
      return;
    }
    if (stateController.text.isEmpty) {
      btnController.reset();
      Toast.showToast("Please Enter State");
      return;
    }
    if (postcodeController.text.isEmpty) {
      btnController.reset();
      Toast.showToast("Please Enter Postcode");
      return;
    }

    // Handle image upload if selected
    if (profileImage != null) {
      btnController.start();
      final uploadedUrl = await uploadImageAndSave(File(profileImage!.path));
      if (uploadedUrl == null) {
        btnController.reset();
        Toast.showToast("Image upload failed. Please try again.");
        return;
      }
      url = uploadedUrl;
    } else {
      url = null; // Optional: send empty or placeholder
    }

    // Now safe to create tenant
    createTenantUser();
  }

  createTenantUser() async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    DateTime now = DateTime.now();

    todayDate = DateFormat("yyyy-MM-dd").format(now);
    validityDate = DateTime(now.year + 1, now.month, now.day).toString();

    deviceId = prefs.getString('deviceId');

    final request = CreateTenantUser(
      tenantimage: url, // Now correctly set

      configid: 1,
      allocationid: 2,
      roleid: 1,
      tenantname: companyNameController.text,
      tenanttype: "D",
      registrationno: gstinNumberController.text,
      devicetype: Platform.isAndroid ? "android" : "ios",
      deviceid: deviceId ?? '',
      tenanttoken: fcmEntryToken ?? '',
      companyname: companyNameController.text,
      firstname: firstnameController.text,
      primaryemail: emailController.text,
      primarycontact: contactNoController.text,
      categoryid: catId,
      subcategoryid: subCatId,
      moduleid: 2,
      address: addressController.text,
      suburb: suburbController.text,
      state: stateController.text,
      city: cityController.text,
      postcode: postcodeController.text,
      latitude: latitude,
      longitude: longitude,
      applocationid: 1,
      approved: 0,

      tenantlocations: Tenantlocations(
        locationid: 0,
        applocationid: appLocationId,
        tenantid: 0,
        moduleid: 2,
        locationname: companyNameController.text,
        email: emailController.text,
        contactno: contactNoController.text,
        address: addressController.text,
        suburb: suburbController.text,
        state: stateController.text,
        city: cityController.text,
        postcode: postcodeController.text,
        latitude: latitude,
        longitude: longitude,
        partnerid: partnerId,
        opentime: "09:00",
        closetime: "21:00",
        deliverytype: 0,
        deliverymins: 60,
        cancelsecs: 20,
      ),

      tenantsubscriptions: Tenantsubscriptions(
        subscriptionid: 0,
        tenantid: 0,
        transactiondate: todayDate,
        moduleid: 2,
        applocationid: appLocationId,
        categoryid: catId,
        subcategoryid: subCatId,
        validitydate: validityDate?.split(' ')[0] ?? '',
        subscriptionprice: 300.00,
        quantity: 1,
        taxamount: 0.00,
        taxpercent: 18,
        totalamount: 300.00,
        paymentstatus: 1,
      ),
    );

    createTenantUserResult(request);
  }

  createTenantUserResult(CreateTenantUser data) async {
    SharedPreferences prefs = await SharedPreferences.getInstance();

    CreateTenantUserResponse? result = await createTenantUserRepository.createTenantUser(data);
    if (result?.status == true) {
      await Future.wait([
        prefs.setInt('userId', result?.details?.userid ?? 0),
        prefs.setInt('configId', result?.details?.configid ?? 0),
        prefs.setString('userEmail', result?.details?.authname ?? ''),
        prefs.setInt('authMode', result?.details?.authmode ?? 0),
        prefs.setInt('roleId', result?.details?.roleid ?? 0),
        prefs.setString('userFirstname', result?.details?.firstname ?? ''),
        prefs.setString('userLastname', result?.details?.lastname ?? ''),
        prefs.setString('userName', result?.details?.fullname ?? ''),
        prefs.setString('password', result?.details?.password ?? ''),
        prefs.setString('userEmail', result?.details?.email ?? ''),
        prefs.setString('tenantContactNo', result?.details?.contactno ?? ''),
        prefs.setString('userAddress', result?.details?.address ?? ''),
        prefs.setString('userSuburb', result?.details?.suburb ?? ''),
        prefs.setString('userCity', result?.details?.city ?? ''),
        prefs.setString('userState', result?.details?.state ?? ''),
        prefs.setString('userPostcode', result?.details?.postcode ?? ''),
        prefs.setString('userFcmToken', result?.details?.userfcmtoken ?? ''),
        prefs.setInt('userPin', result?.details?.pin ?? 0),
        prefs.setInt('partnerId', result?.details?.partnerid ?? 0),
        prefs.setInt('locationId', result?.details?.locationid ?? 0),
        prefs.setInt('tenantId', result?.details?.tenantid ?? 0),
        prefs.setString('tenantName', result?.details?.tenantname ?? ''),
        prefs.setString('tenantAddress', result?.details?.address ?? ''),
        prefs.setString('tenantSuburb', result?.details?.suburb ?? ''),
        prefs.setString('tenantCity', result?.details?.city ?? ''),
        prefs.setString('tenantState', result?.details?.state ?? ''),
        prefs.setString('tenantPostcode', result?.details?.postcode ?? ''),
        prefs.setInt('moduleId', result?.details?.moduleid ?? 0),
        prefs.setString('locationName', result?.details?.locationname ?? ''),
        prefs.setInt('categoryId', result?.details?.categoryid ?? 0),
        prefs.setInt('subcategoryId', result?.details?.subcategoryid ?? 0),
        prefs.setInt('appLocationId', result?.details?.applocationid ?? 0),
      ]);

      logger.i('TenantId From Create Tenant Response: ${prefs.getInt('tenantId')}');

      // Clear fields
      firstnameController.clear();
      companyNameController.clear();
      emailController.clear();
      addressController.clear();
      suburbController.clear();
      cityController.clear();
      stateController.clear();
      postcodeController.clear();
      profileImage = null;
      url = null;

      btnController.reset();
      update();
      await Future.delayed(Duration(milliseconds: 100));
      Get.to(() => AccountCreatedScreen());
    } else {
      btnController.reset();
      Toast.showToast("${result?.message}");
    }
  }

  Future<Position> getLocation() async {
    LocationPermission permission = await Geolocator.checkPermission();
    if (permission == LocationPermission.denied) {
      permission = await Geolocator.requestPermission();
      if (permission == LocationPermission.denied) {
        return Future.error('Location permissions are denied');
      }
    }
    if (permission == LocationPermission.deniedForever) {
      await Geolocator.openLocationSettings();
      return Future.error('Location permissions are permanently denied');
    }
    Position position = await Geolocator.getCurrentPosition();
    await getAddressFromLatLongs(position.latitude, position.longitude);
    logger.i(position);
    return position;
  }

  XFile? profileImage;
  final _picker = ImagePicker();
  RxString uploadedFileUrl = ''.obs;

  // Only pick image — upload later
  Future getProfileImage() async {
    final XFile? selectedImage = await _picker.pickImage(source: ImageSource.gallery);
    if (selectedImage != null) {
      profileImage = selectedImage;
      update();
    } else {
      Toast.showToast('Image Not Selected');
    }
  }

  // Upload image and return public URL
  Future<String?> uploadImageAndSave(File selectedImage) async {
    try {
      var rng = Random();
      const String region = "sgp1";
      const String accessKey = "DO00NQER7N2FRYZAB2HR";
      const String secretKey = "nMDewX25IBEu1FM5dakK+v28/WbW3TzBAwq913+dxP0";
      const String bucketName = "nearle";
      const String folderName = "deals";

      String fileName = 'profile-${rng.nextInt(1000)}-1234.jpg';
      String endpointUrl = "https://$bucketName.$region.digitaloceanspaces.com/$folderName/$fileName";

      final minio = Minio(
        endPoint: '$region.digitaloceanspaces.com', // ✅ FIXED HERE
        accessKey: accessKey,
        secretKey: secretKey,
        region: region,
        useSSL: true,
      );

      await minio.fPutObject(
        bucketName,
        '$folderName/$fileName',
        selectedImage.path,
        metadata: {
          'Content-Type': 'image/jpeg',
          'x-amz-acl': 'public-read',
        },
      );

      print("File uploaded successfully: $endpointUrl");
      return endpointUrl;
    } catch (e) {
      Get.snackbar("Error", "Image upload failed: $e");
      print("Upload error: $e");
      return null;
    }
  }

  @override
  void onInit() {
    getFcmToken();
    getLocation();
    getSubCategories();
    getAppCategory();
    super.onInit();
  }

  @override
  void dispose() {
    firstnameController.dispose();
    lastnameController.dispose();
    companyNameController.dispose();
    emailController.dispose();
    gstinNumberController.dispose();
    contactNoController.dispose();
    addressController.dispose();
    stateController.dispose();
    cityController.dispose();
    suburbController.dispose();
    postcodeController.dispose();
    super.dispose();
  }
}

class SubCategoryService {
  final String apiUrl = "https://fiesta.nearle.app/live/api/v1/mob/utils/getsubcategories";

  Future<GetSubCategoriesResponse?> fetchSubCategories() async {
    try {
      final response = await http.get(Uri.parse(apiUrl));
      if (response.statusCode == 200) {
        final jsonData = json.decode(response.body);
        print(response.body);
        return GetSubCategoriesResponse.fromJson(jsonData);
      } else {
        print("Failed to load subcategories: ${response.statusCode}");
      }
    } catch (e) {
      print("Error fetching subcategories: $e");
    }
    return null;
  }
}