import 'dart:ui';

import 'package:hmg_patient_app/config/config.dart';
import 'package:hmg_patient_app/core/model/labs/LabOrderResult.dart';
import 'package:hmg_patient_app/core/model/labs/lab_result.dart';
import 'package:hmg_patient_app/core/model/labs/patient_lab_orders.dart';
import 'package:hmg_patient_app/core/model/labs/patient_lab_special_result.dart';
import 'package:hmg_patient_app/core/model/labs/request_patient_lab_special_result.dart';
import 'package:hmg_patient_app/core/model/labs/request_send_lab_report_email.dart';
import 'package:hmg_patient_app/core/service/base_service.dart';
import 'package:hmg_patient_app/models/Authentication/authenticated_user.dart';
import 'package:hmg_patient_app/uitl/date_uitl.dart';
import 'package:hmg_patient_app/widgets/data_display/medical/LabResult/lab_result_graph.dart';

class LabsService extends BaseService {
  List<PatientLabOrders> patientLabOrdersList = [];

  String labReportPDF = "";

  Future getPatientLabOrdersList() async {
    hasError = false;
    Map<String, dynamic> body = Map();
    body['isDentalAllowedBackend'] = false;
    await baseAppClient.post(GET_Patient_LAB_ORDERS, onSuccess: (dynamic response, int statusCode) {
      patientLabOrdersList.clear();
      response['ListPLO'].forEach((hospital) {
        patientLabOrdersList.add(PatientLabOrders.fromJson(hospital));
      });
    }, onFailure: (String error, int statusCode) {
      hasError = true;
      super.error = error;
    }, body: body);
  }

  RequestPatientLabSpecialResult _requestPatientLabSpecialResult = RequestPatientLabSpecialResult();

  List<PatientLabSpecialResult> patientLabSpecialResult = [];
  List<LabResult> labResultList = [];
  List<LabOrderResult> labOrdersResultsList = [];

  Future getLaboratoryResult({String? projectID, int? clinicID, String? invoiceNo, String? invoiceType, String? orderNo, String? setupID, bool? isVidaPlus}) async {
    hasError = false;
    _requestPatientLabSpecialResult.projectID = projectID;
    _requestPatientLabSpecialResult.clinicID = clinicID;

    _requestPatientLabSpecialResult.invoiceNo = isVidaPlus! ? "0" : invoiceNo;
    _requestPatientLabSpecialResult.invoiceNoVP = isVidaPlus ? invoiceNo : "0";

    _requestPatientLabSpecialResult.invoiceType = invoiceType ?? "";

    _requestPatientLabSpecialResult.orderNo = orderNo;
    _requestPatientLabSpecialResult.setupID = setupID;

    await baseAppClient.post(GET_Patient_LAB_SPECIAL_RESULT, onSuccess: (dynamic response, int statusCode) {
      patientLabSpecialResult.clear();
      response['ListPLSR'].forEach((hospital) {
        patientLabSpecialResult.add(PatientLabSpecialResult.fromJson(hospital));
      });
    }, onFailure: (String error, int statusCode) {
      hasError = true;
      super.error = error;
    }, body: _requestPatientLabSpecialResult.toJson());
  }

  Future getPatientLabResult({PatientLabOrders? patientLabOrder, bool? isVidaPlus}) async {
    hasError = false;
    Map<String, dynamic> body = Map();
    body['InvoiceNo_VP'] = isVidaPlus! ? patientLabOrder!.invoiceNo : "0";
    body['InvoiceNo'] = isVidaPlus ? "0" : patientLabOrder!.invoiceNo;
    body['InvoiceType'] = patientLabOrder!.invoiceType;
    body['OrderNo'] = patientLabOrder!.orderNo;
    body['isDentalAllowedBackend'] = false;
    body['SetupID'] = patientLabOrder.setupID;
    body['ProjectID'] = patientLabOrder.projectID;
    body['ClinicID'] = patientLabOrder.clinicID;
    await baseAppClient.post(GET_Patient_LAB_RESULT, onSuccess: (dynamic response, int statusCode) {
      patientLabSpecialResult.clear();
      labResultList.clear();
      response['ListPLR'].forEach((lab) {
        labResultList.add(LabResult.fromJson(lab));
      });
    }, onFailure: (String error, int statusCode) {
      hasError = true;
      super.error = error;
    }, body: body);
  }

  Future generateCovidLabReport(LabResult covidLabResult, String isOutsideKSA) async {
    hasError = false;
    Map<String, dynamic> body = Map();

    body['To'] = user.emailAddress;
    body['OrderNo'] = covidLabResult.orderNo;
    body['OrderLineItemNo'] = covidLabResult.orderLineItemNo;
    body['LineItemNo'] = covidLabResult.resultValueBasedLineItemNo;
    body['CertificateFormat'] = 5;
    body['GeneratedBy'] = 102;
    body['ShowPassportNumber'] = isOutsideKSA;
    body['isDentalAllowedBackend'] = false;
    body['SetupID'] = covidLabResult.setupID;
    body['ProjectID'] = covidLabResult.projectID;

    dynamic localRes;

    await baseAppClient.post(SEND_COVID_LAB_RESULT_EMAIL, onSuccess: (dynamic response, int statusCode) {
      localRes = response;
    }, onFailure: (String error, int statusCode) {
      hasError = true;
      super.error = error;
    }, body: body);
    return Future.value(localRes);
  }

  Future updateCovidPassportNumber(String passportNumber) async {
    hasError = false;
    Map<String, dynamic> body = Map();

    body['PassportNo'] = passportNumber;

    dynamic localRes;

    await baseAppClient.post(COVID_PASSPORT_UPDATE, onSuccess: (dynamic response, int statusCode) {
      localRes = response;
    }, onFailure: (String error, int statusCode) {
      hasError = true;
      super.error = error;
    }, body: body);
    return Future.value(localRes);
  }

  Future updateWorkplaceName(String workplaceName, String workplaceNameAR, String occupation, String occupationAR, int requestNumber, String setupID, int projectID) async {
    // Future updateWorkplaceName(String workplaceName, String workplaceNameAR, int requestNumber, String setupID, int projectID) async {
    hasError = false;
    Map<String, dynamic> body = Map();

    body['Placeofwork'] = workplaceName;
    body['PlaceofworkAr'] = workplaceNameAR;
    body['Occupation'] = occupation;
    body['OccupationAr'] = occupationAR;
    body['Req_ID'] = requestNumber;
    body['TargetSetupID'] = setupID;
    body['ProjectID'] = projectID;
    body['UserID'] = 102;
    body['RequestType'] = 1;

    dynamic localRes;

    await baseAppClient.post(UPDATE_WORKPLACE_NAME, onSuccess: (dynamic response, int statusCode) {
      localRes = response;
    }, onFailure: (String error, int statusCode) {
      hasError = true;
      super.error = error;
    }, body: body);
    return Future.value(localRes);
  }

  Future getCovidPassportNumber() async {
    hasError = false;
    Map<String, dynamic> body = Map();

    dynamic localRes;

    await baseAppClient.post(GET_PATIENT_PASSPORT_NUMBER, onSuccess: (dynamic response, int statusCode) {
      localRes = response;
    }, onFailure: (String error, int statusCode) {
      hasError = true;
      super.error = error;
    }, body: body);
    return Future.value(localRes);
  }

  Future getSickLeaveStatusByAdmissionNo(int projectID, int admissionNo) async {
    hasError = false;
    Map<String, dynamic> body = Map();

    body['AdmissionNo'] = admissionNo;
    body['ProjectID'] = projectID;

    dynamic localRes;

    await baseAppClient.post(GET_SICKLEAVE_STATUS_ADMISSION_NO, onSuccess: (dynamic response, int statusCode) {
      localRes = response;
    }, onFailure: (String error, int statusCode) {
      hasError = true;
      super.error = error;
    }, body: body);
    return Future.value(localRes);
  }

  Future getPatientLabOrdersResults({PatientLabOrders? patientLabOrder, String? procedure, bool isVidaPlus = false}) async {
    hasError = false;
    Map<String, dynamic> body = Map();
    body['InvoiceNo_VP'] = isVidaPlus ? patientLabOrder!.invoiceNo : "0";
    body['InvoiceNo'] = isVidaPlus ? "0" : patientLabOrder!.invoiceNo;
    body['OrderNo'] = patientLabOrder!.orderNo;
    body['isDentalAllowedBackend'] = false;
    body['SetupID'] = patientLabOrder!.setupID;
    body['ProjectID'] = patientLabOrder.projectID;
    body['ClinicID'] = patientLabOrder.clinicID;
    body['Procedure'] = procedure;
    body['Procedure'] = procedure;
    body['LanguageID'] = 1;
    await baseAppClient.post(GET_Patient_LAB_ORDERS_RESULT, onSuccess: (dynamic response, int statusCode) {
      labOrdersResultsList.clear();
      response['ListPLR'].forEach((lab) {
        labOrdersResultsList.add(LabOrderResult.fromJson(lab));
      });
      labOrdersResultsList = labOrdersResultsList.reversed.toList();
    }, onFailure: (String error, int statusCode) {
      labOrdersResultsList.clear();
      hasError = true;
      super.error = error;
    }, body: body);
  }

  RequestSendLabReportEmail _requestSendLabReportEmail = RequestSendLabReportEmail();

  Future sendLabReportEmail({PatientLabOrders? patientLabOrder, AuthenticatedUser? userObj, bool isVidaPlus = false, bool isDownload = false, int languageID = 1}) async {
    _requestSendLabReportEmail.projectID = patientLabOrder!.projectID;
    _requestSendLabReportEmail.invoiceNo = isVidaPlus ? "0" : patientLabOrder.invoiceNo;
    _requestSendLabReportEmail.invoiceNoVP = isVidaPlus ? patientLabOrder.invoiceNo : "0";
    _requestSendLabReportEmail.invoiceType = patientLabOrder.invoiceType;
    _requestSendLabReportEmail.doctorName = patientLabOrder.doctorName;
    _requestSendLabReportEmail.clinicName = patientLabOrder.clinicDescription;
    _requestSendLabReportEmail.patientName = userObj!.firstName! + " " + userObj.lastName!;
    _requestSendLabReportEmail.patientIditificationNum = userObj.patientIdentificationNo;
    _requestSendLabReportEmail.dateofBirth = userObj.dateofBirth;
    _requestSendLabReportEmail.to = userObj.emailAddress;
    _requestSendLabReportEmail.orderDate = '${patientLabOrder.orderDate!.year}-${patientLabOrder.orderDate!.month}-${patientLabOrder.orderDate!.day}';
    _requestSendLabReportEmail.patientMobileNumber = userObj.mobileNumber;
    _requestSendLabReportEmail.projectName = patientLabOrder.projectName;
    _requestSendLabReportEmail.setupID = patientLabOrder.setupID;
    _requestSendLabReportEmail.orderNo = patientLabOrder.orderNo;
    _requestSendLabReportEmail.orderNo = patientLabOrder.orderNo;
    _requestSendLabReportEmail.isDownload = isDownload;
    _requestSendLabReportEmail.doctorID = patientLabOrder.doctorID;
    _requestSendLabReportEmail.languageID = languageID;

    // await baseAppClient.post(SEND_LAB_RESULT_EMAIL, onSuccess: (dynamic response, int statusCode) {
    await baseAppClient.post(isVidaPlus ? SEND_LAB_RESULT_EMAIL : SEND_LAB_RESULT_EMAIL_NEW, onSuccess: (dynamic response, int statusCode) {
      if (isDownload) {
        labReportPDF = isVidaPlus ? response['LabReportsPDFContent'] : response['PdfContent'];
      }
    }, onFailure: (String error, int statusCode) {
      hasError = true;
      super.error = error;
    }, body: _requestSendLabReportEmail.toJson());
  }

  List<LabOrderResult> sortByFlagAndValue(List<LabOrderResult> original) {
    const priorityOrder = ['LCL', 'CL', 'L', 'N', 'H', 'CH', 'HCH'];

    int getFlagPriority(String? flag) {
      if (flag == null) return priorityOrder.length;
      final index = priorityOrder.indexOf(flag);
      return index == -1 ? priorityOrder.length : index;
    }

    double parseResultValue(String? value) {
      if (value == null) return double.nan;
      return double.tryParse(value) ?? double.nan;
    }

    final copy = List<LabOrderResult>.from(original);
    copy.sort((a, b) {
      final aFlagPriority = getFlagPriority(a.calculatedResultFlag);
      final bFlagPriority = getFlagPriority(b.calculatedResultFlag);

      if (aFlagPriority != bFlagPriority) {
        return aFlagPriority.compareTo(bFlagPriority);
      }

      final aValue = parseResultValue(a.resultValue);
      final bValue = parseResultValue(b.resultValue);

      return aValue.compareTo(bValue);
    });

    return copy;
  }

  Map<String, LabOrderResult> mapFirstItemByPriority(
      List<LabOrderResult> sortedResults) {
    final Map<String, LabOrderResult> priorityMap = {};
    const priorityOrder = ['LCL', 'CL', 'L', 'N', 'H', 'CH', 'HCH'];
    for (final result in sortedResults) {
      final priority = result.calculatedResultFlag?.trim();
      if (priority != null &&
          priorityOrder.contains(priority) &&
          !priorityMap.containsKey(priority)) {
        priorityMap[priority] = result;
      }

      // Early exit if all priorities are found
      if (priorityMap.length == priorityOrder.length) break;
    }
    print("the map of priority is :\n $priorityMap");
    return priorityMap;
  }

  List<LabOrderResult> getMostRecentThree(List<LabOrderResult> original) {
    DateTime? parseVerifiedDate(String? raw) {
      if (raw == null) return null;
      final regex = RegExp(r'\/Date\((\d+)\)\/');
      final match = regex.firstMatch(raw);
      if (match != null) {
        print("the match iss not null");
        final millis = int.tryParse(match.group(1)!);
        if (millis != null) {
          print(
              "the data and time is ${DateTime.fromMillisecondsSinceEpoch(millis)}");
          return DateTime.fromMillisecondsSinceEpoch(millis);
        }
      }
      return null;
    }

    final copy = List<LabOrderResult>.from(original);
    copy.sort((a, b) {
      final aDate = DateUtil.convertStringToDate(a.verifiedOnDateTime);
      final bDate = DateUtil.convertStringToDate(b.verifiedOnDateTime);
      if (aDate == null && bDate == null) return 0;
      if (aDate == null) return 1;
      if (bDate == null) return -1;
      return bDate.compareTo(aDate); // descending
    });

    // print("the copied item are $copy");
    labOrdersResultsList = copy;
    return copy.take(3).toList();
  }

  List<ThresholdRange> buildThresholdList(List<LabOrderResult> topResults) {
    var mapOfPriority = mapFirstItemByPriority(topResults);
    return mapResultToThreshold(topResults, mapOfPriority);
  }

  List<ThresholdRange> mapResultToThreshold(
      List<LabOrderResult> results, Map<String, LabOrderResult> mapOfPriority) {
    // Extract valid numeric results
    List<double> actualValues = results
        .map((e) => double.tryParse(e.resultValue ?? ''))
        .where((v) => v != null)
        .cast<double>()
        .toList();

    if (actualValues.isEmpty) return [];

    actualValues.sort();
    double min = actualValues.first;
    double max = actualValues.last;

    double baseRange = max - min;

    // Handle single value or equal values
    if (baseRange == 0) {
      baseRange = max * 0.2; // ±10%
      min = max - baseRange / 2;
      max = max + baseRange / 2;
    }

    // Adjust range scale based on number of actual values
    // >5 = compress thresholds; <5 = expand thresholds
    int valueCount = actualValues.length;
    double scalingFactor = valueCount >= 5 ? 1.0 : (5 / valueCount);

    double adjustedRange = baseRange * scalingFactor;

    // Recalculate thresholds based on adjusted range
    // double criticalLow = min;
    // double low = min + 0.25 * adjustedRange;
    // double normal = min + 0.5 * adjustedRange;
    // double high = min + 0.75 * adjustedRange;
    // double criticalHigh = min + adjustedRange;
    const priorityOrder = ['LCL', 'CL', 'L', 'N', 'H', 'CH', 'HCH'];

    var mapOfValues = inferThresholds(mapOfPriority);
    var item = results.first;
    String? realCriticalLow =
    (item.criticalLow == "0") ? null : item.criticalLow;
    String? realReferenceHigh =
    (item.referenceHigh == "0") ? null : item.referenceHigh;
    String? realCriticalHigh =
    (item.criticalHigh == "0") ? null : item.criticalHigh;
    String? realReferenceLow =
    (item.referenceLow == "0") ? null : item.referenceLow;
    final adjustedValues = adjustValues(
      criticalLow: mapOfValues['criticalLow'],
      low: mapOfValues['low'],
      normal: mapOfValues['normal'],
      high: mapOfValues['high'],
      criticalHigh: mapOfValues['criticalHigh'],
    );

    return [
      ThresholdRange(
          label: 'Critical Low',
          value: adjustedValues["criticalLow"]!,
          color: Color(0xffffffff),
          lineColor: Color(0xFFe9a2a4),
          actualValue: realCriticalLow),
      ThresholdRange(
          label: 'Low',
          value: adjustedValues['low']!,
          color: Color(0xFFf2fbf5),
          lineColor: Color(0xFFefc481),
          actualValue: realReferenceLow),
      ThresholdRange(
          label: 'Normal',
          value: adjustedValues['normal']!,
          color: Color(0xFFf2fbf5),
          lineColor: Color(0xFF5dc36b)),
      ThresholdRange(
          label: 'High',
          value: adjustedValues['high']!,
          color: Color(0xffffffff),
          lineColor: Color(0xFFefc481),
          actualValue: realReferenceHigh),
      ThresholdRange(
          label: 'Critical High',
          value: adjustedValues['criticalHigh']!,
          color: Color(0xffffffff),
          lineColor: Color(0xFFe9a2a4),
          actualValue: realCriticalHigh),
    ];
  }

  Map<String, double> inferThresholds(
      Map<String, LabOrderResult> mapOfPriority) {
    double? parse(String? v) {
      final parsed = double.tryParse(v ?? '');
      return (parsed == null || parsed < 0) ? null : parsed;
    }

    // Parse inputs
    double? criticalLow = parse(
        mapOfPriority['LCL']?.resultValue ?? mapOfPriority['CL']?.resultValue);
    double? low = parse(mapOfPriority['L']?.resultValue);
    double? normal = parse(mapOfPriority['N']?.resultValue);
    double? high = parse(mapOfPriority['H']?.resultValue);
    double? criticalHigh = parse(
        mapOfPriority['CH']?.resultValue ?? mapOfPriority['HCH']?.resultValue);

    const step = 5.0;
    List<double?> values = [criticalLow, low, normal, high, criticalHigh];
    // Find the index of the known value (priority: central -> left -> right)
    int anchorIndex = values.indexWhere((v) => v != null);
    double anchorValue = values[anchorIndex] ?? 50;

    // Infer all values around the anchor
    List<double> inferred = List.generate(5, (i) {
      double v = anchorValue + (i - anchorIndex) * step;
      return v < 0 ? 0 : v;
    });
    var mapresult = {
      'criticalLow': values[0]??-1,
      'low': values[1]??-1,
      'normal': values[2]??-1,
      'high': values[3]??-1,
      'criticalHigh': values[4]??-1,
    };

    print("the result is $mapresult");
    return mapresult;
  }

  Map<String, double> adjustValues({
    double? criticalLow,
    double? low,
    double? normal,
    double? high,
    double? criticalHigh,
    double step = 10,
  }) {
    bool criticalLowHasValue = true;
    bool lowHasValue = true;
    bool normaHasValue = true;
    bool highHasValue = true;
    bool criticalHighHasValue = true;

    if (criticalLow == null || criticalLow == -1) criticalLowHasValue = false;
    if (low == null || low == -1) lowHasValue = false;
    if (normal == null ||normal ==-1) normaHasValue = false;
    if (high == null ||high ==-1) highHasValue = false;
    if (criticalHigh == null ||criticalHigh ==-1) criticalHighHasValue = false;

    print("the values arre $criticalLowHasValue $lowHasValue $normaHasValue $highHasValue $criticalHighHasValue");
    if (!criticalLowHasValue) {
      criticalLow = 0;
      if (lowHasValue) {
        low = low! - step;
      }  if (normaHasValue && (criticalLow!= 0 || criticalLow != -1)) {
        low = normal! - step * 2;
      }  if (highHasValue  && (criticalLow!= 0 || criticalLow != -1)) {
        low = high! - step * 3;
      }  if (criticalHighHasValue  && (criticalLow!= 0 || criticalLow != -1)) {
        low = criticalHigh! - step * 4;
      }
    }
    if (!lowHasValue) {
      print("the low value is not set");
      low = 0;

      if (criticalLowHasValue && (low != 0 || low != -1)) {
        low = criticalLow! + step;
      }  if (normaHasValue && (low != 0 || low != -1)) {
        low = normal! - step;
      }  if (highHasValue && (low != 0 || low != -1)) {
        low = high! - step * 2;
      }  if (criticalHighHasValue && (low != 0 || low != -1)) {
        low = criticalHigh! - step * 3;
      }

    }
    if (!normaHasValue) {
      normal = 0;

      if (criticalLowHasValue && (normal != 0 || normal != -1)) {
        normal = criticalLow! + step * 2;
      }  if (lowHasValue) {
        normal = low! + step;
      }  if (highHasValue) {
        normal = high! - step;
      }  if (criticalHighHasValue) {
        normal = criticalHigh! - step * 2;
      }
    }
    if (!highHasValue) {
      high = 0;

      if (criticalLowHasValue) {
        high = criticalLow! + step * 3;
      }  if (lowHasValue) {
        high = low! + step * 2;
      }  if (normaHasValue) {
        high = normal! + step;
      }  if (criticalHighHasValue) {
        high = criticalHigh! - step;
      }
    }
    if (!criticalHighHasValue) {

      criticalHigh = 0;

      if (criticalLowHasValue) {
        criticalHigh = criticalLow! + step * 4;
      }  if (lowHasValue) {
        criticalHigh = low! + step * 3;
      }  if (normaHasValue) {
        criticalHigh = normal! + step * 2;
      }  if (highHasValue) {
        criticalHigh = high! + step;
      }
    }
    if(((criticalLow??0)<0) == true){
      var mod = ((low ?? 0)  + (normal??0) )/2;
      criticalLow = mod;
    }

    if(((low??0)<0) == true){
      var mod = ((criticalLow ?? 0)  + (normal??0) )/2;
      low = mod;
    }

    if(((normal??0)<0) == true){
      var mod = ((low ?? 0)  + (high??0) )/2;
      normal = mod;
    }
    if(((high??0)<0) == true){
      var mod = ((normal ?? 0)  + (criticalHigh??0) )/2;
      high = mod;
    }

    if(((criticalHigh??0)<0) == true){
      criticalHigh = (high??0)+step;
    }



    Map<String, double?> values = {
      'criticalLow':criticalLow ,
      'low': low,
      'normal':  normal ,
      'high':  high ,
      'criticalHigh':  criticalHigh,
    };
    print("thee adjusted values `are $values");

    // // Find the first known value
    // int firstKnownIndex = values.values.toList().indexWhere((v) => v != null);
    //
    // if (firstKnownIndex == -1) {
    //   // No values at all, start from 0
    //   values = {
    //     'criticalLow': 0,
    //     'low': step,
    //     'normal': step * 2,
    //     'high': step * 3,
    //     'criticalHigh': step * 4,
    //   };
    // } else {
    //   // Fill backward
    //   for (int i = firstKnownIndex - 1; i >= 0; i--) {
    //     values[values.keys.elementAt(i)] =
    //         (values.values.elementAt(i + 1)! - step).clamp(0, double.infinity);
    //   }
    //
    //   // Fill forward
    //   for (int i = firstKnownIndex + 1; i < values.length; i++) {
    //     values[values.keys.elementAt(i)] =
    //         values.values.elementAt(i - 1)! + step;
    //   }
    // }
    //
    // // Ensure strictly increasing sequence
    // double prev = -double.infinity;
    // values.forEach((key, val) {
    //   if (val! <= prev) {
    //     values[key] = prev + step;
    //   }
    //   prev = values[key]!;
    // });

    return values.map((k, v) => MapEntry(k, v!));
  }

  void adjustLabOrderResults(List<LabOrderResult> results) {
    const priorityOrder = ['LCL', 'CL', 'L', 'N', 'H', 'CH', 'HCH'];

    // Sort results by priority order
    results.sort((a, b) => priorityOrder
        .indexOf(a.calculatedResultFlag ?? '')
        .compareTo(priorityOrder.indexOf(b.calculatedResultFlag ?? '')));

    // Extract values
    List<double?> values = results.map((r) {
      double? v = double.tryParse(r.resultValue ?? '');
      return (v != null && v >= 0) ? v : null;
    }).toList();

    // Find first non-null index
    int? firstIdx = values.indexWhere((v) => v != null);
    if (firstIdx == -1) return; // All values missing

    // Fill before first known value (decreasing with step 5, not less than 0)
    for (int i = firstIdx - 1; i >= 0; i--) {
      values[i] = (values[i + 1]! - 5).clamp(0, double.infinity);
    }

    // Fill after first known value (increasing with step 5)
    for (int i = firstIdx + 1; i < values.length; i++) {
      if (values[i] == null) {
        values[i] = values[i - 1]! + 5;
      }
    }

    // For gaps in the middle, interpolate
    for (int i = 0; i < values.length; i++) {
      if (values[i] == null) {
        // find next non-null
        int j = i + 1;
        while (j < values.length && values[j] == null) j++;
        if (j < values.length) {
          double start = values[i - 1]!;
          double end = values[j]!;
          double step = (end - start) / (j - i + 1);
          for (int k = i; k < j; k++) {
            values[k] = start + step * (k - i + 1);
          }
        }
      }
    }

    // Update results list directly
    for (int i = 0; i < results.length; i++) {
      results[i].resultValue = values[i]?.toStringAsFixed(2) ?? '0.00';
    }
  }

  double transformValueInRange(double inputValue, String flag) {
    // Define range boundaries
    double rangeStart, rangeEnd;

    switch (flag) {
      case 'CL':
        rangeStart = 0.0;
        rangeEnd = 19.0;
        break;
      case 'L':
        rangeStart = 20.0;
        rangeEnd = 39.0;
        break;
      case 'N':
        rangeStart = 40.0;
        rangeEnd = 59.0;
        break;
      case 'H':
        rangeStart = 60.0;
        rangeEnd = 79.0;
        break;
      case 'CH':
        rangeStart = 80.0;
        rangeEnd = 100.0;
        break;
      default:
        throw ArgumentError('Invalid flag: $flag');
    }

    // Clamp input value to 0-100 and map it to the range bounds
    final clampedValue = inputValue.clamp(0.0, 100.0);
    final normalizedValue = clampedValue / 100.0; // Normalize input to 0-1

    // Map the normalized value to the target range bounds
    final transformedValue = rangeStart + (normalizedValue * (rangeEnd - rangeStart));

    return transformedValue;
  }



  List<ThresholdRange> getThresholdValue() {
    return [
      ThresholdRange(
          label: 'LCL',
          value: 0,
          color: Color(0xffffffff),
          lineColor: Color(0xFFe9a2a4)), ThresholdRange(
          label: 'CL',
          value: 0,
          color: Color(0xffffffff),
          lineColor: Color(0xFFe9a2a4)),
      ThresholdRange(
          label: 'L',
          value: 20,
          color: Color(0xFFf2fbf5),
          lineColor: Color(0xFFeecd94)),
      ThresholdRange(
          label: 'N',
          value: 40,
          color: Color(0xFFf2fbf5),
          lineColor: Color(0xFF5dc36b)),
      ThresholdRange(
          label: 'H',
          value: 60,
          color: Color(0xffffffff),
          lineColor: Color(0xFFeecd94)),
      ThresholdRange(
          label: 'CH',
          value: 80,
          color: Color(0xffffffff),
          lineColor: Color(0xFFe9a2a4)), ThresholdRange(
          label: 'HCH',
          value: 80,
          color: Color(0xffffffff),
          lineColor: Color(0xFFe9a2a4)),
    ];
  }


}









