import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'base_field.dart';
import 'dynamic_dropdown_field.dart';
import '../ui/entity_form.dart';

/// Dependent dropdown field that loads options based on another field's value
/// This field automatically makes API calls when the dependent field changes
class DependentDropdownField extends BaseField {
  final String fieldKey;
  final String label;
  final String hint;
  final bool isRequired;
  final String dependentFieldKey; // The field this dropdown depends on
  final Future<List<Map<String, dynamic>>> Function(String parentValue)
      optionsLoader; // Loader using parent value
  final String valueKey; // Field name for value in API response
  final String displayKey; // Field name for display text in API response
  final Map<String, dynamic>? customProperties;

  DependentDropdownField({
    required this.fieldKey,
    required this.label,
    required this.hint,
    this.isRequired = false,
    required this.dependentFieldKey,
    required this.optionsLoader,
    this.valueKey = 'id',
    this.displayKey = 'name',
    this.customProperties,
  });

  @override
  String? Function(String?)? get validator => (value) {
        if (isRequired && (value == null || value.isEmpty)) {
          return '$label is required';
        }
        return null;
      };

  @override
  Widget buildField({
    required TextEditingController controller,
    required ColorScheme colorScheme,
    VoidCallback? onChanged,
  }) {
    return _DependentDropdownWidget(
      fieldKey: fieldKey,
      label: label,
      hint: hint,
      isRequired: isRequired,
      dependentFieldKey: dependentFieldKey,
      optionsLoader: optionsLoader,
      valueKey: valueKey,
      displayKey: displayKey,
      controller: controller,
      colorScheme: colorScheme,
      onChanged: onChanged,
    );
  }
}

class _DependentDropdownWidget extends StatefulWidget {
  final String fieldKey;
  final String label;
  final String hint;
  final bool isRequired;
  final String dependentFieldKey;
  final Future<List<Map<String, dynamic>>> Function(String parentValue)
      optionsLoader;
  final String valueKey;
  final String displayKey;
  final TextEditingController controller;
  final ColorScheme colorScheme;
  final VoidCallback? onChanged;

  const _DependentDropdownWidget({
    required this.fieldKey,
    required this.label,
    required this.hint,
    required this.isRequired,
    required this.dependentFieldKey,
    required this.optionsLoader,
    required this.valueKey,
    required this.displayKey,
    required this.controller,
    required this.colorScheme,
    this.onChanged,
  });

  @override
  State<_DependentDropdownWidget> createState() =>
      _DependentDropdownWidgetState();
}

class _DependentDropdownWidgetState extends State<_DependentDropdownWidget> {
  String? _lastDependentValue;
  Key _reloadKey = const ValueKey('init');

  @override
  void initState() {
    super.initState();
    // Defer inherited widget access until after first frame
    WidgetsBinding.instance.addPostFrameCallback((_) {
      if (mounted) {
        _checkDependentFieldChange();
      }
    });
  }

  void _loadInitialOptions() async {}

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    _checkDependentFieldChange();
  }

  void _checkDependentFieldChange() {
    final formScope = EntityFormScope.of(context);
    if (formScope != null) {
      final dependentController =
          formScope.controllers[widget.dependentFieldKey];
      if (dependentController != null) {
        final currentValue = dependentController.text;
        if (currentValue != _lastDependentValue) {
          _lastDependentValue = currentValue;
          // Defer mutations to next frame to avoid setState during build
          WidgetsBinding.instance.addPostFrameCallback((_) {
            if (!mounted) return;
            // Clear current selection when parent changes
            widget.controller.clear();
            // Force re-init of inner DynamicDropdown by changing key
            setState(() {
              _reloadKey = ValueKey(
                  'dep-${widget.fieldKey}-${_lastDependentValue ?? 'empty'}-${DateTime.now().millisecondsSinceEpoch}');
            });
            // Notify parent about change
            widget.onChanged?.call();
          });
        }
      }
    }
  }

  @override
  Widget build(BuildContext context) {
    Future<List<Map<String, dynamic>>> loadOptions() async {
      // If no dependent value selected, return empty
      final formScope = EntityFormScope.of(context);
      final depVal =
          formScope?.controllers[widget.dependentFieldKey]?.text ?? '';
      if (depVal.isEmpty) return const [];

      try {
        final response = await widget.optionsLoader(depVal);
        return response
            .map((item) => {
                  widget.valueKey: item[widget.valueKey]?.toString() ?? '',
                  widget.displayKey: item[widget.displayKey]?.toString() ?? '',
                })
            .toList();
      } catch (e) {
        // Return empty list on error to prevent showing old data
        return const [];
      }
    }

    final innerField = DynamicDropdownField(
      fieldKey: widget.fieldKey,
      label: widget.label,
      hint: widget.hint,
      isRequired: widget.isRequired,
      optionsLoader: loadOptions,
      valueKey: widget.valueKey,
      displayKey: widget.displayKey,
    );

    final child = innerField.buildField(
      controller: widget.controller,
      colorScheme: widget.colorScheme,
      onChanged: widget.onChanged,
    );

    // Read current parent value for UI guard/notice
    final formScope = EntityFormScope.of(context);
    final depVal = formScope?.controllers[widget.dependentFieldKey]?.text ?? '';

    final keyedChild = KeyedSubtree(key: _reloadKey, child: child);

    final content = Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        // If parent is empty, block interactions and show subtle disabled state
        if (depVal.isEmpty)
          Opacity(
            opacity: 0.6,
            child: AbsorbPointer(child: keyedChild),
          )
        else
          keyedChild,
        if (depVal.isEmpty)
          Padding(
            padding: const EdgeInsets.only(top: 6.0),
            child: Text(
              'Please select ${widget.dependentFieldKey} first',
              style: TextStyle(
                color: widget.colorScheme.onSurface.withOpacity(0.7),
                fontSize: 12,
              ),
            ),
          ),
      ],
    );

    return content;
  }
}

/// Helper class to manage dependent dropdown relationships
/// This should be used in EntityForm to handle field dependencies
class DependentDropdownManager {
  static final Map<String, List<DependentDropdownField>> _dependencies = {};

  /// Register a dependent dropdown field
  static void registerDependency(
      String dependentFieldKey, DependentDropdownField field) {
    if (!_dependencies.containsKey(dependentFieldKey)) {
      _dependencies[dependentFieldKey] = [];
    }
    _dependencies[dependentFieldKey]!.add(field);
  }

  /// Get all dependent fields for a given field
  static List<DependentDropdownField> getDependentFields(String fieldKey) {
    return _dependencies[fieldKey] ?? [];
  }

  /// Clear all dependencies (useful for form reset)
  static void clearDependencies() {
    _dependencies.clear();
  }

  /// Notify dependent fields when a field value changes
  static void notifyDependentFields(String fieldKey, String value) {
    final dependentFields = getDependentFields(fieldKey);
    for (final field in dependentFields) {
      // This would need to be implemented with proper context
      // The actual implementation would be in EntityForm
    }
  }
}
