import 'dart:async';
import 'dart:core';
import 'package:amplify_flutter/amplify_flutter.dart';
//import 'dart:ffi';
import 'package:flutter/material.dart';

import 'package:get/get.dart';
import 'package:get_storage/get_storage.dart';
import 'package:trialOrderPro/app/routes.dart';
import 'package:trialOrderPro/modules/cart/controllers/cart_controller.dart';
import 'package:trialOrderPro/data/model/brand_data_model.dart';
import 'package:trialOrderPro/data/model/customer_data_model.dart';
import 'package:trialOrderPro/data/helper/database_helper.dart';
import 'package:trialOrderPro/ui/screens/brands/brand_selection_screen.dart';
import 'package:trialOrderPro/utils/internet/network_util.dart';
import 'package:trialOrderPro/modules/cart/controllers/aws_s3_controller.dart';
import 'package:trialOrderPro/utils/local_storage/app_local_storage.dart';
import 'package:trialOrderPro/ui/dialogs/dialogs.dart';
import '../../../utils/constant/key_constant.dart';
import 'package:trialOrderPro/utils/enum/enums.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';

class OutsideFitsetController extends GetxController {
  final List<String> brands = [
    'BTOD SVS', 'BTOD FP', 'BTOD FA',
    'INFUSE SVS', 'INFUSE FP', //'INFUSE FA',
    'ULTRA SVS', 'ULTRA FP', 'ULTRA FA', 'ULTRA MFA',
    // 'EUREKA DAILY', 'EUREKA MONTHLY', 'LC DAILY' --> These are white lable Brands -- will be enabled later if required.
  ].obs;

  List<String> powersfilterata = [
    '+6.00',
    '+5.75',
    '+5.50',
    '+5.25',
    '+5.00',
    '+4.75',
    '+4.50',
    '+4.25',
    '+4.00',
    '+3.75',
    '+3.50',
    '+3.25',
    '+3.00',
    '+2.75',
    '+2.50',
    '+2.25',
    '+2.00',
    '+1.75',
    '+1.50',
    '+1.25',
    '+1.00',
    '+0.75',
    '+0.50',
    '+0.25',
    '0.00',
    '-0.25',
    '-0.50',
    '-0.75',
    '-1.00',
    '-1.25',
    '-1.50',
    '-1.75',
    '-2.00',
    '-2.25',
    '-2.50',
    '-2.75',
    '-3.00',
    '-3.25',
    '-3.50',
    '-3.75',
    '-4.00',
    '-4.25',
    '-4.50',
    '-4.75',
    '-5.00',
    '-5.25',
    '-5.50',
    '-5.75',
    '-6.00',
    '-6.25',
    '-6.50',
    '-6.75',
    '-7.00',
    '-7.25',
    '-7.50',
    '-7.75',
    '-8.00',
    '-8.25',
    '-8.50',
    '-8.75',
    '-9.00',
    '-9.25',
    '-9.50',
    '-9.75',
  ].obs;

  List<String> cylindersfilterData =
      ['-0.75', '-1.25', '-1.75', '-2.25', '-2.75'].obs;
  List<String> axisfilterData = [
    '10',
    '20',
    '30',
    '40',
    '50',
    '60',
    '70',
    '80',
    '90',
    '100',
    '110',
    '120',
    '130',
    '140',
    '150',
    '160',
    '170',
    '180'
  ].obs;
  List<String> addfilteData = ['High', 'Low'].obs;

  RxString? selectedBrand = RxString('');
  RxString? selectedIndication = RxString('');
  RxString? selectedPower = RxString('');
  RxString? selectedCylinder = RxString('');
  RxString? selectedAxis = RxString('');
  RxString? selectedAdd = RxString('');
  RxString? sku = RxString('');
  dynamic customerInfo;
  RxBool isCustomerSelected = false.obs;
  AppLocalStorage appLocalStorage = AppLocalStorage();
  final cartController = Get.put(CartController());
  RxBool isLoading = false.obs;
  final resetTrigger = 0.obs;
  RxBool isAddedToCart = false.obs;

  void setLoading(value) {
    isLoading.value = value;
  }

  String formatPower(String power) {
    if (power.length != 4) return power;

    String sign = power.substring(0, 1);
    String wholePart = power.substring(1, 2);
    String decimalPart = power.substring(2);

    // // Remove leading zero from whole part if it's not the only digit
    // if (wholePart.startsWith('0') && wholePart != '00') {
    //   wholePart = wholePart.substring(1);
    // }

    return '$sign$wholePart.$decimalPart';
  }

  String formatCylinder(String cylinder) {
    if (cylinder.length == 2) {
      return '-0.${cylinder}';
    } else if (cylinder.length == 3) {
      String wholePart = cylinder.substring(0, 1);
      String decimalPart = cylinder.substring(1);
      return '-$wholePart.$decimalPart';
    } else {
      return cylinder;
    }
  }

  void getOutsideFitLensDataFromAWSBucket() async {
    setLoading(true);
    bool isNetwork = await NetworkUtil.isNetworkAvailable();
    if (isNetwork) {
      var awsController = Get.put(AwsController());
      try {
        if (!Amplify.isConfigured) {
          await awsController.configureAmplify();
        }
        var outsidefitsetlensdata =
            await awsController.downloadOutSideFitsetDrawerData();
        final headerRow =
            outsidefitsetlensdata.isNotEmpty ? outsidefitsetlensdata.first : [];

        for (final row in outsidefitsetlensdata.skip(1)) {
          final Map<String, dynamic> rowMap = {};
          for (int i = 0; i < headerRow.length && i < row.length; i++) {
            rowMap[headerRow[i].toString()] = row[i];
          }

          String productid = rowMap['PRODUCT_ID']?.toString() ?? '';
          String sku = rowMap['UPC']?.toString() as String;

          if (!productid.contains('INFU10') &&
              !productid.contains('XULS') &&
              !productid.contains('UOGS') &&
              !productid.contains('UOBS') &&
              !productid.contains('ZJS') &&
              !productid.contains('UA05')) {
            String brand = '';
            String description = '';

            int indexofsign = productid.contains('+')
                ? productid.indexOf('+')
                : productid.indexOf('-');

            String sign = productid.substring(indexofsign, indexofsign + 1);

            brand = productid.toString().split(sign)[0];
            description = productid.toString().split(sign)[1];

            String brandValue = '';
            String indication = '';
            String power = '';
            String cylinder = '';
            String axis = '';
            String add = '';

            switch (brand) {
              case KeyConstant.BTODSVS:
                brandValue = BrandData.BioTrueOneDay.value;
                indication = IndicationData.BTOD_SVS.value;
                break;

              case KeyConstant.BTODFA:
                brandValue = BrandData.BioTrueOneDay.value;
                indication = IndicationData.BTOD_FA.value;
                cylinder = description.substring(4, 7);
                axis = description.substring(7, 10);
                String axisfirstplace = axis.substring(0, 1);
                axis = axisfirstplace == '0'
                    ? axis.substring(
                        1,
                      )
                    : axis;

                if (cylinder.length == 2) {
                  cylinder = '-0.${cylinder}';
                } else if (cylinder.length == 3) {
                  String wholePart = cylinder.substring(0, 1);
                  String decimalPart = cylinder.substring(1);
                  cylinder = '-$wholePart.$decimalPart';
                }
                break;

              case KeyConstant.BTODFP:
                brandValue = BrandData.BioTrueOneDay.value;
                indication = IndicationData.BTOD_FP.value;
                add = description.contains('H') ? 'High' : 'Low';
                break;

              case KeyConstant.INFUSESVS:
                brandValue = BrandData.Infuse.value;
                indication = IndicationData.Infuse_SVS.value;
                break;

              case KeyConstant.INFUSEFP:
                brandValue = BrandData.Infuse.value;
                indication = IndicationData.Infuse_FP.value;
                add = description.contains('H') ? 'High' : 'Low';
                break;

              case KeyConstant.ULTRASVS:
                brandValue = BrandData.Ultra.value;
                indication = IndicationData.Ultra_SVS.value;
                break;

              case KeyConstant.ULTRAFA:
                brandValue = BrandData.Ultra.value;
                indication = IndicationData.Ultra_FA.value;
                cylinder = description.substring(4, 7);
                axis = description.substring(7, 10);
                String axisfirstplace = axis.substring(0, 1);
                axis = axisfirstplace == '0'
                    ? axis.substring(
                        1,
                      )
                    : axis;
                if (cylinder.length == 2) {
                  cylinder = '-0.${cylinder}';
                } else if (cylinder.length == 3) {
                  String wholePart = cylinder.substring(0, 1);
                  String decimalPart = cylinder.substring(1);
                  cylinder = '-$wholePart.$decimalPart';
                }
                break;

              case KeyConstant.ULTRAFP:
                brandValue = BrandData.Ultra.value;
                indication = IndicationData.Ultra_FP.value;
                add = description.contains('H') ? 'High' : 'Low';
                break;

              case KeyConstant.ULTRAMFA:
                brandValue = BrandData.Ultra.value;
                indication = IndicationData.Ultra_MFA.value;
                cylinder = description.substring(4, 7);
                axis = description.substring(7, 10);
                String axisfirstplace = axis.substring(0, 1);
                axis = axisfirstplace == '0'
                    ? axis.substring(
                        1,
                      )
                    : axis;
                add = description.contains('L') ? 'Low' : 'High';
                if (cylinder.length == 2) {
                  cylinder = '-0.${cylinder}';
                } else if (cylinder.length == 3) {
                  String wholePart = cylinder.substring(0, 1);
                  String decimalPart = cylinder.substring(1);
                  cylinder = '-$wholePart.$decimalPart';
                }
                break;
              default:
            }

            power = description.substring(0, 4);
            String wholePart = power.substring(0, 1);
            if(wholePart != '0'){
              wholePart = power.substring(0, 2);
            }else{
              wholePart = power.substring(1, 2);
            }
            String decimalPart = power.substring(2);
            power = '$sign$wholePart.$decimalPart';
            power = power == '-0.00' ? '0.00' : power == '+0.00' ? '0.00' : power;

            await _insertOutsideFitLens(
              sku: sku,
              brand: brandValue,
              indication: indication,
              power: power,
              cylinder: cylinder,
              axis: axis,
              add: add,
            );
          }
        }
        setLoading(false);
        appLocalStorage.saveOutSideFitSetDataCall('completed');
      } catch (e) {
        print('Error fetching data: $e');
        appLocalStorage.saveOutSideFitSetDataCall('not-completed');
      }
    } else {
      print("No network available");
      appLocalStorage.saveOutSideFitSetDataCall('not-completed');
    }
  }

  void addLensValueToCart() async {
    String skuValue = await getSku(selectedBrand!, selectedPower!,
        selectedCylinder!, selectedAxis!, selectedAdd!);

    if (skuValue != 'sku not found' && skuValue != 'filter not selected') {
      CustomerData? customerData = CustomerData.getCustomerDataFromStorage();
      String? customerId = customerData?.Id_From_LocalDB.toString();

      BrandDataModel brandDataModel = BrandDataModel(
        brand: skuValue.split('#')[1],
        indication: selectedBrand!.value,
        drawer: 'Individual Lens',
        lensKey: skuValue,
        lensValue: selectedPower!.value,
        sku: skuValue.split('#')[0],
        customerId: customerId!,
        axis: selectedAxis!.value != '' ? selectedAxis!.value + '°' : '',
        range: [],
        cyl: selectedCylinder!.value,
        lowAdd: selectedAdd!.value == 'Low' ? "Low" : '',
        highAdd: selectedAdd!.value == 'High' ? "High" : '',
      );

      cartController.addLensValue(brandDataModel);
      resetSelections();

      isAddedToCart.value = true;
      Future.delayed(Duration(seconds: 5), () {
        isAddedToCart.value = false;
      });

      var context = Get.context;
      if (context != null) {
        var currentRoute = Get.currentRoute;
        showSnackBarFunBottom(true, currentRoute, context);
      }
    }else if (skuValue == 'filter not selected') {
        showAlertDialog("Individual Lens", "Select correct filters!",
          (bool isProceed) => {if (isProceed) {}});
    }else{
      showAlertDialog("Individual Lens", "Trial Lens not found!",
          (bool isProceed) => {if (isProceed) {}});
          
    }
  }

  Future<String> getSku(RxString brand, RxString power, RxString cylinder,
      RxString axis, RxString add) async {
    List<Map<String, dynamic>> outsidefitsetdata = [];
    final db = await DatabaseHelper.instance.database;

    String queryString =
        "SELECT sku, brand FROM outside_fit_lens_table WHERE indication='$brand' and power='$power'";

    if (brand.contains('FP') && power != '' && add != '') {
      queryString += " and addValue like'$add%'";

      outsidefitsetdata = await db.rawQuery(queryString);

      if (outsidefitsetdata.length != 0) {
        return outsidefitsetdata[0]['sku'] +
            '#' +
            outsidefitsetdata[0]['brand'];
      } else {
        return 'sku not found';
      }
    } else if (brand.contains('FA') && power != '' && cylinder != '' && axis != '') {
      queryString += " and cylinder='$cylinder'";
      queryString += " and axis='$axis'";

      outsidefitsetdata = await db.rawQuery(queryString);

      if (outsidefitsetdata.length != 0) {
        return outsidefitsetdata[0]['sku'] +
            '#' +
            outsidefitsetdata[0]['brand'];
      } else {
        return 'sku not found';
      }
    }else if (brand.contains('MFA') && power != '' && cylinder != '' && axis != '' && add != '') {
      queryString += " and cylinder='$cylinder'";
      queryString += " and axis='$axis'";
      queryString += " and addValue like'$add%'";

      outsidefitsetdata = await db.rawQuery(queryString);

      if (outsidefitsetdata.length != 0) {
        return outsidefitsetdata[0]['sku'] +
            '#' +
            outsidefitsetdata[0]['brand'];
      } else {
        return 'sku not found';
      }
    }else if (brand.contains('SVS') && power != '' ){
      outsidefitsetdata = await db.rawQuery(queryString);

        if (outsidefitsetdata.length != 0) {
          return outsidefitsetdata[0]['sku'] +
              '#' +
              outsidefitsetdata[0]['brand'];
        } else {
          return 'sku not found';
      }
    }else {
       return 'filter not selected';
    }

    // if (isCylinderEnabled() && cylinder != '') {
    // queryString += " and cylinder='$cylinder'";
    // }

    // if (isAxisEnabled() && axis != '') {
    //   queryString += " and axis='$axis'";
    // }

    // if (isAddEnabled() && add != '') {
    //   queryString += " and addValue like'$add%'";
    // }

    // String queryString = "SELECT sku FROM outside_fit_lens_table WHERE indication='$brand' and power='$power' and cylinder='$cylinder' and axis='$axis' and addValue='$add'";
    // outsidefitsetdata = await db.rawQuery(queryString);

    // if (outsidefitsetdata.length != 0) {
    //   return outsidefitsetdata[0]['sku'] +'#'+ outsidefitsetdata[0]['brand'];
    // } else {
    //   return 'sku not found';
    // }
  }

  Future<void> _insertOutsideFitLens({
    required String sku,
    required String brand,
    required String indication,
    required String power,
    required String cylinder,
    required String axis,
    required String add,
  }) async {
    final db = await DatabaseHelper.instance.database;
    List<Map<String, dynamic>> existingRecords = await db.query(
      'outside_fit_lens_table',
      where: 'sku = ?',
      whereArgs: [sku],
    );

    if (existingRecords.isEmpty) {
      await db.insert('outside_fit_lens_table', {
        'sku': sku,
        'brand': brand,
        'indication': indication,
        'power': power,
        'cylinder': cylinder,
        'axis': axis,
        'addValue': add,
        'qty': 1,
      });
    } else {
      // int currentQty = existingRecords[0]['qty'] as int;
      await db.update(
        'outside_fit_lens_table',
        {'qty': '1'},
        where: 'sku = ?',
        whereArgs: [sku],
      );
    }
  }

  Future<List<Map<String, dynamic>>> getOutsideFitLensData() async {
    final db = await DatabaseHelper.instance.database;
    final List<Map<String, dynamic>> result =
        await db.query('outside_fit_lens_table');
    return result;
  }

  Future<void> updatePowersDataOnBrandsSelection(String indication) async {
    powersfilterata = <String>[];
    final db = await DatabaseHelper.instance.database;

    String queryString =
        "SELECT power FROM outside_fit_lens_table WHERE indication='$indication' group by power";
    List<Map<String, dynamic>> outsidefitsetdata = [];
    outsidefitsetdata = await db.rawQuery(queryString);

    if (outsidefitsetdata.length != 0) {  
          powersfilterata = outsidefitsetdata.map((e) => e['power'] as String).toList();

      List lint = outsidefitsetdata.map((e) => num.tryParse(e['power'] as String)).toList();

      int c, d;
      double swap;

        for(c = 1; c < lint.length; c++)
        {
            for (d = 0; d < lint.length - c; d++) 
            {
                if (lint[d] < lint[d+1])
                {
                    swap = lint[d];
                    lint[d] = lint[d+1];
                    lint[d+1] = swap;
                }
            }
        }

      // powersfilterata = lint.map((e) => e.toString().contains(".0") ? e.toString()+'0' : e.toString()).toList();

      powersfilterata = lint.map((e){
    
            String sign = e.toString().contains('-') ? '' : '+' ;
            String wholePart = e.toString().substring(0, 1);
            String decimalPart = e.toString().substring(2);
            e = '$sign$wholePart.$decimalPart';   

            return e.toString();
        }).toList();

      update();
    }
  }

  void updateCylindersDataOnPowersSelection(String power) async {
    cylindersfilterData = [];
    final db = await DatabaseHelper.instance.database;

    String queryString =
        "SELECT cylinder FROM outside_fit_lens_table WHERE power='$power' group by cylinder";
    List<Map<String, dynamic>> outsidefitsetdata = [];
    outsidefitsetdata = await db.rawQuery(queryString);

    if (outsidefitsetdata.length != 0) {
      cylindersfilterData =
          outsidefitsetdata.map((e) => e['cylinder'] as String).toList();
      cylindersfilterData.sort((a, b) => b.compareTo(a));
      update();
    }
  }

  void updateAxisDataOnCylinderSelection(String cylinder) async {
    axisfilterData = [];
    final db = await DatabaseHelper.instance.database;

    String queryString =
        "SELECT axis FROM outside_fit_lens_table WHERE cylinder='$cylinder' group by axis";
    List<Map<String, dynamic>> outsidefitsetdata = [];
    outsidefitsetdata = await db.rawQuery(queryString);

    if (outsidefitsetdata.length != 0) {
      axisfilterData =
          outsidefitsetdata.map((e) => e['axis'] as String).toList();
      axisfilterData.sort((a, b) => b.compareTo(a));
      update();
    }
  }

  bool isPowerEnabled() {
    return true;
  }

  bool isCylinderEnabled() {
    if (selectedBrand!.value.isEmpty) return true;
    if (selectedBrand!.value.contains('FA') ||
        selectedBrand!.value == 'ULTRA MFA') {
      return true;
    }
    return false;
  }

  bool isAxisEnabled() {
    return isCylinderEnabled();
  }

  bool isAddEnabled() {
    if (selectedBrand!.value.isEmpty) return true;
    if (selectedBrand!.value.contains('FP') ||
        selectedBrand!.value == 'ULTRA MFA') {
      return true;
    }
    return false;
  }

  void resetSelections() {
    selectedBrand?.value = '';
    selectedIndication?.value = '';
    selectedPower?.value = '';
    selectedCylinder?.value = '';
    selectedAxis?.value = '';
    selectedAdd?.value = '';
    sku?.value = '';
    resetTrigger.value++;

    powersfilterata = [
      '+6.00',
      '+5.75',
      '+5.50',
      '+5.25',
      '+5.00',
      '+4.75',
      '+4.50',
      '+4.25',
      '+4.00',
      '+3.75',
      '+3.50',
      '+3.25',
      '+3.00',
      '+2.75',
      '+2.50',
      '+2.25',
      '+2.00',
      '+1.75',
      '+1.50',
      '+1.25',
      '+1.00',
      '+0.75',
      '+0.50',
      '+0.25',
      '0.00',
      '-0.25',
      '-0.50',
      '-0.75',
      '-1.00',
      '-1.25',
      '-1.50',
      '-1.75',
      '-2.00',
      '-2.25',
      '-2.50',
      '-2.75',
      '-3.00',
      '-3.25',
      '-3.50',
      '-3.75',
      '-4.00',
      '-4.25',
      '-4.50',
      '-4.75',
      '-5.00',
      '-5.25',
      '-5.50',
      '-5.75',
      '-6.00',
      '-6.25',
      '-6.50',
      '-6.75',
      '-7.00',
      '-7.25',
      '-7.50',
      '-7.75',
      '-8.00',
      '-8.25',
      '-8.50',
      '-8.75',
      '-9.00',
      '-9.25',
      '-9.50',
      '-9.75',
    ].obs;

    cylindersfilterData = ['-0.75', '-1.25', '-1.75', '-2.25', '-2.75'].obs;
    axisfilterData = [
      '10',
      '20',
      '30',
      '40',
      '50',
      '60',
      '70',
      '80',
      '90',
      '100',
      '110',
      '120',
      '130',
      '140',
      '150',
      '160',
      '170',
      '180'
    ].obs;
    addfilteData = ['High', 'Low'].obs;
  }

  showSnackBarFunBottom(status, String currentRoute, context) {
    SnackBar snackBar = SnackBar(
      content: Text(status == true ? "Individual Lens added to Cart!" : "",
          style: TextStyle(fontSize: 20, color: Colors.white)),
      backgroundColor: status ? Colors.green : Colors.red,
      dismissDirection: DismissDirection.down,
      behavior: SnackBarBehavior.floating,
      margin: EdgeInsets.all(0),
    );

    //ScaffoldMessenger.of(context).showSnackBar(snackBar);
  }

  showSnackBarFun(status, String currentRoute, context) {
    var top = MediaQuery.of(context).padding.top;
    var height = AppBar().preferredSize.height;
    var size = Size.fromHeight(60);

    var gapFromTop;
    if (currentRoute == AppRoutesPath.outsidefitset) {
      gapFromTop = top + height + 60 + size.height;
    } else {
      gapFromTop = top + height + 60;
    }

    SnackBar snackBar = SnackBar(
      content: Text(status == true ? "Individual Lens added to Cart!" : "",
          style: TextStyle(fontSize: 20, color: Colors.white)),
      backgroundColor: status ? Colors.green : Colors.red,
      dismissDirection: DismissDirection.up,
      behavior: SnackBarBehavior.fixed,
      margin: EdgeInsets.only(
        bottom: MediaQuery.of(context).size.height - gapFromTop,
      ),
    );

    //ScaffoldMessenger.of(context).showSnackBar(snackBar);
  }
}

read teh entire file carefully, and here
powersfilterata = lint.map((e){
    
            String sign = e.toString().contains('-') ? '' : '+' ;
            String wholePart = e.toString().substring(0, 1);
            String decimalPart = e.toString().substring(2);
            e = '$sign$wholePart.$decimalPart';   

            return e.toString();
        }).toList();

this is not giving output properly , as some value missing third digit and some first zero is missing like that.