import 'package:fis_i18n/i18n.dart';
import 'package:fis_theme/theme.dart';
import 'package:fis_ui/index.dart';
import 'package:flutter/material.dart';
import 'package:flutter_picker/Picker.dart';
import 'package:flyinsono/architecture/services/modules/area_region.dart';
import 'package:flyinsono/pages/components/select.dart' as cs;
import 'package:get/get.dart';

///区域选择UI树
class AreaSelectTree extends StatefulWidget implements FWidget {
  AreaSelectTree({
    Key? key,
    this.onIsChinaAreaChanged,
    this.onCountryChanged,
    this.onProvinceChanged,
    this.onCityChanged,
    this.fontSize,
    this.left = 0,
    this.bottom = 0,
    this.right = 0,
    this.top = 0,
    this.boxDecoration,
    this.initCountry,
    this.initProvince,
    this.initcity,
  }) : super(key: key);

  ///中国区域变化事件回调
  final ValueCallback<bool>? onIsChinaAreaChanged;

  ///国家级区域变化事件回调
  final ValueCallback<String>? onCountryChanged;

  ///省级区域变化事件回调
  final ValueCallback<String>? onProvinceChanged;

  ///市级区域变化事件回调
  final ValueCallback<String>? onCityChanged;

  ///字号
  final int? fontSize;

  ///区域选择UI树状态
  final _AreaSelectTreeState state = _AreaSelectTreeState();

  ///左边距
  final double? left;

  ///下边距
  final double? bottom;

  ///右边距
  final double? right;

  ///上边距
  final double? top;

  ///初始化城市
  final String? initcity;

  ///初始化省
  final String? initProvince;

  ///初始化国家
  final String? initCountry;

  ///外围装饰器
  final BoxDecoration? boxDecoration;

  @override
  State<StatefulWidget> createState() => state;

  /// 调起底部弹出选择器
  ///
  /// [onConfirm] 确认回调
  ///
  /// [onCancel] 取消回调
  static Future showPicker(
    BuildContext context, {
    void Function(List<String> codes, List<String> names, bool isChina)?
        onConfirm,
    void Function()? onCancel,
    String? selectedCode,
  }) async {
    final areaRegionService = Get.find<AreaRegionService>();

    final countries = areaRegionService.findTopGradeList();
    final data = _AreaPickerHepler.buildPickerItemTree(
      countries,
      areaRegionService.allList,
    );

    List<int>? selecteds;
    if (selectedCode != null && selectedCode.isNotEmpty) {
      for (var i = 0; i < data.length; i++) {
        final provinces = data[i].children ?? [];
        for (var j = 0; j < provinces.length; j++) {
          final cities = provinces[j].children ?? [];
          for (var k = 0; k < cities.length; k++) {
            final city = cities[k].value!;
            if (city.code == selectedCode) {
              selecteds = [i, j, k];
            }
          }
        }
      }
    }

    final picker = await Picker(
      adapter: PickerDataAdapter<AreaRegionModel>(
        data: data,
      ),
      selecteds: selecteds,
      height: 280,
      changeToFirst: true,
      headerColor: Colors.grey[200],
      selectedTextStyle: const TextStyle(
        color: Colors.black,
        fontSize: 18,
      ),
      confirmTextStyle: TextStyle(
        color: FTheme.ins.colorScheme.primary,
        fontSize: 16,
      ),
      cancelTextStyle: const TextStyle(
        color: Colors.black54,
        fontSize: 16,
      ),
      confirmText: i18nBook.common.confirm.t,
      cancelText: i18nBook.common.cancel.t,
      containerColor: Colors.white,
      onConfirm: (picker, value) {
        final codes = <String>[];
        final names = <String>[];
        var curSource = data;
        value.forEach((i) {
          final item = curSource[i];
          codes.add(item.value!.code);
          names.add(item.value!.name);
          curSource = item.children ?? [];
        });
        final isChina = areaRegionService.judgeIsChinaCode(codes[0]);
        onConfirm?.call(codes, names, isChina);
      },
      onCancel: onCancel,
    ).showModal(context);
    return picker;
  }
}

///区域选择UI树状态
class _AreaSelectTreeState extends State<AreaSelectTree> {
  final areaRegionService = Get.find<AreaRegionService>();
  final cs.FSelectController<AreaRegionModel> countryController =
      cs.FSelectController();
  final cs.FSelectController<AreaRegionModel> provinceController =
      cs.FSelectController();
  final cs.FSelectController<AreaRegionModel> cityController =
      cs.FSelectController();

  final provinceKey = ValueKey("province");
  final cityKey = ValueKey("city");

  /// 生成的地区列表
  List<String> regionList = [];

  bool get isChinaArea => areaRegionService
      .judgeIsChinaCode(countryController.selection?.code ?? "");

  @override
  void didUpdateWidget(covariant AreaSelectTree oldWidget) {
    super.didUpdateWidget(oldWidget);
    if (widget.initcity != oldWidget.initcity && widget.initcity!.isNotEmpty) {
      loadData(widget.initcity!);
    }
  }

  @override
  FWidget build(BuildContext context) {
    FWidget child = FContainer(
      child: FRow(
        children: [
          FFlexible(
            child: _buildCountrySelect(
              fontsize: widget.fontSize,
              left: widget.left,
              right: widget.right,
              bottom: widget.bottom,
              top: widget.top,
            ),
          ),
          FFlexible(
            key: provinceKey,
            child: _buildProvinceSelect(
              fontsize: widget.fontSize,
              left: widget.left,
              right: widget.right,
              bottom: widget.bottom,
              top: widget.top,
            ),
          ),
          FFlexible(
            key: cityKey,
            child: _buildCitySelect(
              fontsize: widget.fontSize,
              left: widget.left,
              right: widget.right,
              bottom: widget.bottom,
              top: widget.top,
            ),
          ),
        ],
      ),
    );

    return FExpanded(
      child: child,
    );
  }

  /// 根据传的code生成地区
  void generateRegionListByCode(String code) {
    final children = areaRegionService.findListByCode(code);
    regionList.add(children.first.code);

    /// 判断是否到顶级
    if (children.first.parentCode != '0') {
      generateRegionListByCode(children.first.parentCode);
    }
  }

  /// 设置省份下拉数据 显示国家名
  void setCountryData(String currCountryCode) {
    countryController.selection = countryController.options.firstWhere(
      (element) => element.code == currCountryCode,
    );
    final provinceOptions =
        areaRegionService.findListByParentCode(currCountryCode);
    provinceController.options = provinceOptions;
  }

  /// 设置城市下拉数据 显示省份名
  void setProvinceData(String currProviceCode) {
    provinceController.selection = provinceController.options.firstWhere(
      (element) => element.code == currProviceCode,
    );
    final cityCodeOptions =
        areaRegionService.findListByParentCode(currProviceCode);
    cityController.options = cityCodeOptions;
  }

  /// 显示城市名
  void setCityData(String currCityCode) {
    cityController.selection = cityController.options.firstWhere(
      (element) => element.code == currCityCode,
    );
  }

  /// 根据区域编码加载数据
  void loadData(
    String regionCode,
  ) {
    if (regionCode.isNotEmpty) {
      WidgetsBinding.instance.addPostFrameCallback((call) {
        regionList = [];
        generateRegionListByCode(regionCode);
        final List<String> regionListReversed =
            regionList.reversed.toSet().toList();
        if (regionListReversed.length != 0) {
          setCountryData(regionListReversed[0]);
          if (regionListReversed.length == 2) {
            setProvinceData(regionListReversed[1]);
          }
          if (regionListReversed.length == 3) {
            setProvinceData(regionListReversed[1]);
            setCityData(regionListReversed[2]);
          }
        }
      });
    }
  }

  @override
  void initState() {
    countryController.addListener(_onCountryUpdate);
    provinceController.addListener(_onProvinceUpdate);
    cityController.addListener(_onCityUpdate);
    WidgetsBinding.instance.addPostFrameCallback((call) {
      if (mounted) {
        _fetchCoutryData();
      }
    });
    super.initState();
  }

  void _onCountryUpdate() {
    widget.onIsChinaAreaChanged?.call(isChinaArea);
    widget.onCountryChanged?.call(countryController.selection?.code ?? "");

    _clearCityAndProvince();
    if (countryController.selection != null) {
      _fetchProvinceData(countryController.selection!.code);
    }
  }

  void _onProvinceUpdate() {
    widget.onProvinceChanged?.call(provinceController.selection?.code ?? "");
    _clearCity();
    if (provinceController.selection != null) {
      _fetchCityData(provinceController.selection!.code);
    }
  }

  void _onCityUpdate() {
    widget.onCityChanged?.call(cityController.selection?.code ?? "");
  }

  void _clearCityAndProvince() {
    setState(() {
      cityController.clear();
      provinceController.clear();
    });
  }

  void _clearCity() {
    setState(() {
      cityController.clear();
    });
  }

  Future<void> _fetchCityData(String parentCode) async {
    final options = areaRegionService.findListByParentCode(parentCode);
    cityController.options = options;
    if (mounted) {
      setState(() {});
    }
  }

  Future<void> _fetchProvinceData(String parentCode) async {
    final options = areaRegionService.findListByParentCode(parentCode);
    provinceController.options = options;
    cityController.selection = null;
    cityController.options = [];
    if (mounted) {
      setState(() {});
    }
  }

  Future<void> _fetchCoutryData() async {
    final options = areaRegionService.findTopGradeList();
    countryController.options = options;
    if (mounted) {
      setState(() {});
    }
  }

  FWidget _buildCountrySelect({
    int? fontsize,
    double? left,
    double? right,
    double? bottom,
    double? top,
  }) {
    return FContainer(
      child: cs.FSelect<AreaRegionModel, String>(
        controller: countryController,
        valueExtractor: (data) => data.code,
        labelExtractor: (data) => data.name,
        hint: i18nBook.common.country.t,
        left: left,
        right: right,
        bottom: bottom,
        top: top,
        boxDecoration: widget.boxDecoration ?? BoxDecoration(),
        fontSize: fontsize,
        onSelectChanged: (data) {
          countryController.selection = data;
        },
      ),
    );
  }

  FWidget _buildProvinceSelect({
    int? fontsize,
    double? left,
    double? right,
    double? bottom,
    double? top,
  }) {
    return FContainer(
      child: cs.FSelect<AreaRegionModel, String>(
        controller: provinceController,
        valueExtractor: (data) => data.code,
        labelExtractor: (data) => data.name,
        hint: i18nBook.common.province.t,
        left: left,
        right: right,
        bottom: bottom,
        top: top,
        fontSize: fontsize,
        boxDecoration: widget.boxDecoration ?? BoxDecoration(),
        onSelectChanged: (data) {
          provinceController.selection = data;
        },
      ),
    );
  }

  FWidget _buildCitySelect({
    int? fontsize,
    double? left,
    double? right,
    double? bottom,
    double? top,
  }) {
    return FContainer(
      child: cs.FSelect<AreaRegionModel, String>(
        controller: cityController,
        valueExtractor: (data) => data.code,
        labelExtractor: (data) => data.name,
        hint: i18nBook.common.city.t,
        left: left,
        right: right,
        bottom: bottom,
        top: top,
        fontSize: fontsize,
        boxDecoration: widget.boxDecoration ?? BoxDecoration(),
        onSelectChanged: (data) {
          cityController.selection = data;
          widget.onCityChanged?.call(data!.code);
        },
      ),
    );
  }

  @override
  void dispose() {
    countryController.removeListener(_onCountryUpdate);
    provinceController.removeListener(_onProvinceUpdate);
    cityController.removeListener(_onCityUpdate);
    countryController.dispose();
    provinceController.dispose();
    cityController.dispose();
    super.dispose();
  }
}

///区域选择帮助类
class _AreaPickerHepler {
  static List<PickerItem<AreaRegionModel>> buildPickerItemTree(
    Iterable<AreaRegionModel> list,
    Iterable<AreaRegionModel> source,
  ) {
    final pickerItemTree = list.map((e) => buildPickerItem(e, source)).toList();
    return pickerItemTree;
  }

  static PickerItem<AreaRegionModel> buildPickerItem(
    AreaRegionModel model,
    Iterable<AreaRegionModel> source,
  ) {
    final pickerItemList = <PickerItem<AreaRegionModel>>[];
    final matchKids = source.where(
      (x) => x.parentCode == model.code,
    );
    for (var kid in matchKids) {
      pickerItemList.add(
        buildPickerItem(
          kid,
          source,
        ),
      );
    }
    final item = PickerItem<AreaRegionModel>(
      children: pickerItemList,
      value: model,
      text: Text(
        model.name,
      ),
    );
    return item;
  }
}
