import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_web/pages/device_managment/all_devices/models/devices_model.dart';
import 'package:syncrow_web/pages/device_managment/flush_mounted_presence_sensor/models/flush_mounted_presence_sensor_model.dart';
import 'package:syncrow_web/pages/routines/bloc/functions_bloc/functions_bloc_bloc.dart';
import 'package:syncrow_web/pages/routines/models/device_functions.dart';
import 'package:syncrow_web/pages/routines/models/flush/flush_functions.dart';
import 'package:syncrow_web/pages/routines/widgets/custom_routines_textbox.dart';
import 'package:syncrow_web/pages/routines/widgets/routine_dialogs/flush_presence_sensor/flush_operational_values_list.dart';
import 'package:syncrow_web/pages/routines/widgets/slider_value_selector.dart';

class FlushValueSelectorWidget extends StatelessWidget {
  final String selectedFunction;
  final DeviceFunctionData functionData;
  final List<FlushFunctions> flushFunctions;
  final AllDevicesModel? device;
  final String dialogType;
  final bool removeComparators;

  const FlushValueSelectorWidget({
    required this.selectedFunction,
    required this.functionData,
    required this.flushFunctions,
    required this.device,
    required this.dialogType,
    required this.removeComparators,
    super.key,
  });

  (double, double) get sliderRange => switch (functionData.functionCode) {
        FlushMountedPresenceSensorModel.codeOccurDistReduce => (0, 3),
        FlushMountedPresenceSensorModel.codeNoneDelay => (200, 3000),
        FlushMountedPresenceSensorModel.codeSensiReduce => (0, 3),
        FlushMountedPresenceSensorModel.codePresenceDelay => (0, 5),
        FlushMountedPresenceSensorModel.codeIlluminance => (0.0, 2000.0),
        FlushMountedPresenceSensorModel.codeFarDetection => (0.0, 9.5),
        FlushMountedPresenceSensorModel.codeNearDetection => (0.0, 9.5),
        _ => (0.0, 100.0),
      };

  double get stepSize => switch (functionData.functionCode) {
        FlushMountedPresenceSensorModel.codeNoneDelay => 10.0,
        FlushMountedPresenceSensorModel.codeFarDetection => 0.5,
        FlushMountedPresenceSensorModel.codeNearDetection => 0.5,
        FlushMountedPresenceSensorModel.codePresenceDelay => 1.0,
        FlushMountedPresenceSensorModel.codeOccurDistReduce => 1.0,
        FlushMountedPresenceSensorModel.codeSensiReduce => 1.0,
        _ => 1.0,
      };

  @override
  Widget build(BuildContext context) {
    final selectedFn = flushFunctions.firstWhere(
      (f) => f.code == selectedFunction,
      orElse: () => throw Exception('Function $selectedFunction not found'),
    );

    if (_isSliderFunction(selectedFunction)) {
      final isNearDetection =
          selectedFunction == FlushMountedPresenceSensorModel.codeNearDetection;
      final isFarDetection =
          selectedFunction == FlushMountedPresenceSensorModel.codeFarDetection;

      final isDistanceDetection = isNearDetection || isFarDetection;
      double initialValue = (functionData.value as num?)?.toDouble() ?? 0.0;

      if (isDistanceDetection) {
        initialValue = initialValue / 100;
      }
      return CustomRoutinesTextbox(
        withSpecialChar: true,
        currentCondition: functionData.condition,
        dialogType: dialogType,
        sliderRange: sliderRange,
        displayedValue: getDisplayText,
        initialValue: initialValue,
        onConditionChanged: (condition) => context.read<FunctionBloc>().add(
              AddFunction(
                functionData: DeviceFunctionData(
                  entityId: device?.uuid ?? '',
                  functionCode: selectedFunction,
                  operationName: functionData.operationName,
                  condition: condition,
                  value: functionData.value ?? 0,
                ),
              ),
            ),
        onTextChanged: (value) {
          final roundedValue = _roundToStep(value, stepSize);
          final finalValue =
              isDistanceDetection ? (roundedValue * 100).toInt() : roundedValue;

          context.read<FunctionBloc>().add(
                AddFunction(
                  functionData: DeviceFunctionData(
                    entityId: device?.uuid ?? '',
                    functionCode: selectedFunction,
                    operationName: functionData.operationName,
                    value: finalValue,
                    condition: functionData.condition,
                  ),
                ),
              );
        },
        unit: _unit,
        dividendOfRange: stepSize,
        stepIncreaseAmount: stepSize,
      );
    }

    return FlushOperationalValuesList(
      values: selectedFn.getOperationalValues(),
      selectedValue: functionData.value,
      device: device,
      operationName: selectedFn.operationName,
      selectCode: selectedFunction,
      onSelect: (selectedValue) async {
        context.read<FunctionBloc>().add(
              AddFunction(
                functionData: DeviceFunctionData(
                  entityId: device?.uuid ?? '',
                  functionCode: selectedFunction,
                  operationName: functionData.operationName,
                  value: selectedValue.value,
                  condition: functionData.condition,
                ),
              ),
            );
      },
    );
  }

  double _roundToStep(double value, double step) {
    return (value / step).roundToDouble() * step;
  }

  bool _isSliderFunction(String function) => [
        FlushMountedPresenceSensorModel.codeOccurDistReduce,
        FlushMountedPresenceSensorModel.codeSensiReduce,
        FlushMountedPresenceSensorModel.codeNoneDelay,
        FlushMountedPresenceSensorModel.codeIlluminance,
        FlushMountedPresenceSensorModel.codePresenceDelay,
        FlushMountedPresenceSensorModel.codeFarDetection,
        FlushMountedPresenceSensorModel.codeNearDetection,
      ].contains(function);

  String get _unit => switch (functionData.functionCode) {
        FlushMountedPresenceSensorModel.codeOccurDistReduce => 'Min',
        FlushMountedPresenceSensorModel.codeSensiReduce => 'Sec',
        FlushMountedPresenceSensorModel.codeNoneDelay => 'Sec',
        FlushMountedPresenceSensorModel.codePresenceDelay => 'Sec',
        FlushMountedPresenceSensorModel.codeIlluminance => 'Lux',
        FlushMountedPresenceSensorModel.codeFarDetection => 'm',
        FlushMountedPresenceSensorModel.codeNearDetection => 'm',
        _ => '',
      };

  String get getDisplayText {
    final num? value = functionData.value;
    double displayValue = value?.toDouble() ?? 0.0;

    if (functionData.functionCode ==
            FlushMountedPresenceSensorModel.codeNearDetection ||
        functionData.functionCode ==
            FlushMountedPresenceSensorModel.codeFarDetection) {
      displayValue = displayValue / 100;
    }

    switch (functionData.functionCode) {
      case FlushMountedPresenceSensorModel.codeFarDetection:
      case FlushMountedPresenceSensorModel.codeNearDetection:
        return displayValue.toStringAsFixed(1);
      case FlushMountedPresenceSensorModel.codeOccurDistReduce:
      case FlushMountedPresenceSensorModel.codeSensiReduce:
      case FlushMountedPresenceSensorModel.codePresenceDelay:
        return displayValue.toStringAsFixed(0);
      default:
        return displayValue.toStringAsFixed(0);
    }
  }
}
