import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/new_views/common_widgets/app_loading_manager.dart';
import 'package:test_sa/providers/loading_list_notifier.dart';
import 'package:test_sa/views/widgets/bottom_sheets/selection_bottom_sheet.dart';
import 'package:test_sa/views/widgets/fullscreen_dialogs/selection_fullscreen_dialog.dart';

import '../../models/base.dart';
import '../app_style/app_color.dart';

class SingleItemDropDownMenu<T extends Base, X extends LoadingListNotifier> extends StatefulWidget {
  final BuildContext context;
  final Function(T?)? onSelect; // Now accepts nullable values
  final T? initialValue;
  final bool enabled;
  final bool showAsBottomSheet;
  final bool showAsFullScreenDialog;
  final List<T>? staticData;
  final String title;
  final double? height;
  final bool showShadow;
  final Color? backgroundColor; // Now nullable
  final bool? loading; // Now nullable

  /// To use a static data (without calling API)
  /// just send [NullableLoadingProvider] as generic data type and fill the [staticData]
  const SingleItemDropDownMenu({
    Key? key,
    this.title = "",
    required this.context,
    this.onSelect,
    this.initialValue,
    this.enabled = true,
    this.height,
    this.showAsBottomSheet = false,
    this.showAsFullScreenDialog = false,
    this.staticData, // Provide a default empty list
    this.showShadow = true,
    this.backgroundColor,
    this.loading,
  }) : super(key: key);

  @override
  State<SingleItemDropDownMenu<T, X>> createState() => _SingleItemDropDownMenuState<T, X>();
}

class _SingleItemDropDownMenuState<T extends Base, X extends LoadingListNotifier> extends State<SingleItemDropDownMenu<T, X>> {
  T? _selectedItem;
  X? provider;

  @override
  void initState() {
    if (X != NullableLoadingProvider) {
      provider = Provider.of<X>(widget.context);
    }
    if (widget.initialValue != null) {
      final result = (X == NullableLoadingProvider ? widget.staticData : provider?.items)?.where((element) => element.identifier == widget.initialValue?.identifier);
      if (result?.isNotEmpty ?? false) _selectedItem = result!.first as T?;
      if (widget.onSelect != null && (widget.initialValue?.identifier ?? "") != (_selectedItem?.identifier ?? "")) {
        widget.onSelect!(_selectedItem); // Non-null assertion after null check
      }
    }
    super.initState();
  }

  @override
  void setState(VoidCallback fn) {
    if (mounted) super.setState(fn);
  }

  @override
  void didUpdateWidget(covariant SingleItemDropDownMenu<T, X> oldWidget) {
    if (widget.initialValue != null) {
      print("$provider:start3:${DateTime.now()}");
      final result = (X == NullableLoadingProvider ? widget.staticData : provider?.items)?.where((element) => element.identifier == widget.initialValue?.identifier);
      print("$provider:start4:${DateTime.now()}");
      if (result?.isNotEmpty ?? false) {
        _selectedItem = result?.first as T?;
      } else {
        _selectedItem = null;
      }
      if (widget.onSelect != null && (widget.initialValue?.identifier ?? "") != (_selectedItem?.identifier ?? "")) {
        widget.onSelect!(_selectedItem); // Non-null assertion after null check
      }
    } else {
      _selectedItem = null;
    }
    super.didUpdateWidget(oldWidget);
  }

  @override
  Widget build(BuildContext context) {
    final isEmpty = (X == NullableLoadingProvider ? widget.staticData : provider?.items)?.isEmpty ?? true;
    return AppLoadingManager(
      isLoading: widget.loading ?? ((X == NullableLoadingProvider) ? false : provider?.loading ?? false),
      // Provide default value if null
      isFailedLoading: (X == NullableLoadingProvider) ? false : provider?.items == null,
      stateCode: (X == NullableLoadingProvider) ? 200 : provider?.stateCode,
      onRefresh: () async {
        if (X != NullableLoadingProvider) {
          provider?.reset();
          await provider?.getDate();
        }
      },
      child: Container(
        height: widget.height ?? 60.toScreenHeight,
        padding: EdgeInsets.symmetric(horizontal: 16.toScreenWidth),
        decoration: BoxDecoration(
          color: context.isDark && (widget.enabled == false || isEmpty)
              ? AppColor.neutral50
              : (widget.enabled == false || isEmpty)
                  ? AppColor.neutral40
                  : widget.backgroundColor ?? AppColor.background(context),
          borderRadius: BorderRadius.circular(10),
          boxShadow: widget.showShadow ? [BoxShadow(color: Colors.black.withOpacity(0.05), blurRadius: 10)] : null,
        ),
        child: Stack(
          alignment: Alignment.center,
          children: [
            if (widget.enabled) const PositionedDirectional(end: 0, child: Icon(Icons.keyboard_arrow_down_rounded)),
            Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                Text(
                  widget.title,
                  style: Theme.of(context).textTheme.bodySmall?.copyWith(color: context.isDark ? null : AppColor.neutral20, fontWeight: FontWeight.w500),
                ),
                DropdownButton<T>(
                  value: _selectedItem,
                  iconSize: 24,
                  isDense: true,
                  icon: const SizedBox.shrink(),
                  dropdownColor: AppColor.neutral100,
                  elevation: 0,
                  isExpanded: true,
                  hint: Text(
                    isEmpty || widget.enabled == false ? context.translation.noDataFound : context.translation.select,
                    style: Theme.of(context).textTheme.bodyLarge,
                  ),
                  style: TextStyle(color: Theme.of(context).primaryColor, fontSize: 12),
                  underline: const SizedBox.shrink(),
                  onChanged: (widget.enabled == false || widget.showAsBottomSheet || widget.showAsFullScreenDialog)
                      ? null
                      : (T? newValue) {
                          // Now accepts nullable values
                          final isNull = newValue?.identifier == "-1";
                          setState(() {
                            _selectedItem = isNull ? null : newValue;
                          });
                          widget.onSelect!(isNull ? null : newValue); // Non-null assertion after null check
                        },
                  items: ((X == NullableLoadingProvider) ? widget.staticData : provider?.items as List<T>)?.map<DropdownMenuItem<T>>((value) {
                    return DropdownMenuItem<T>(
                      value: value,
                      child: Text(
                        value.name ?? "", // Null-aware operator for value.name
                        style: Theme.of(context).textTheme.bodyMedium?.copyWith(fontWeight: FontWeight.w500, color: AppColor.black10),
                      ),
                    );
                  }).toList(),
                ).onPress(widget.showAsFullScreenDialog
                    ? () {
                        openDialog();
                      }
                    : (widget.showAsBottomSheet
                        ? () async {
                            final selectedT = await showModalBottomSheet<T?>(
                              // Specify return type
                              context: context,
                              isScrollControlled: true,
                              shape: const RoundedRectangleBorder(
                                borderRadius: BorderRadius.vertical(
                                  top: Radius.circular(20),
                                ),
                              ),
                              clipBehavior: Clip.antiAliasWithSaveLayer,
                              builder: (BuildContext context) => SelectionBottomSheet<T>(
                                // Specify generic type
                                items: ((X == NullableLoadingProvider) ? widget.staticData : provider?.items as List<T>) ?? [], // Provide default empty list if null
                                selectedItem: _selectedItem,
                                title: widget.title,
                                builderString: (emp) => emp?.name ?? "", // Null-aware operator for emp.name
                              ),
                            );
                            if (selectedT != null) {
                              setState(() {
                                _selectedItem = selectedT;
                              });
                              widget.onSelect!(selectedT); // Non-null assertion after null check
                            }
                          }
                        : null)),
              ],
            ),
          ],
        ),
      ),
    );
  }

  void openDialog() async {
    Widget child = SelectionFullScreenDialog<T>(
      // Specify generic type
      items: ((X == NullableLoadingProvider) ? widget.staticData : provider?.items as List<T>) ?? [], // Provide default empty list if null
      selectedItem: _selectedItem,
      title: widget.title,
      builderString: (emp) => emp?.name ?? "", // Null-aware operator for emp.name
    );

    final selectedT = await pushRouter(child);
    if (selectedT != null) {
      setState(() {
        _selectedItem = selectedT;
      });
      widget.onSelect!(selectedT); // Non-null assertion after null check
    }
  }

  Future<T?> pushRouter(Widget child) async {
    // PageRoute<T> pRoute = !Platform.isIOS ? CupertinoPageRoute(fullscreenDialog: true, builder: (context) => child) : MaterialPageRoute(fullscreenDialog: true, builder: (context) => child);

    return await Navigator.of(context).push(CupertinoPageRoute(fullscreenDialog: true, builder: (context) => child));
  }
}
