import 'package:fis_common/env/env.dart';
import 'package:fis_common/extensions/string.dart';
import 'package:fis_i18n/i18n.dart';

import 'package:fis_jsonrpc/http_pool.dart';
import 'package:flutter/material.dart';
import 'package:flyinsono/architecture/app_parameters.dart';
import 'package:flyinsono/architecture/config/model.dart';
import 'package:flyinsono/architecture/define.dart';
import 'package:flyinsono/architecture/event_bus.dart';
import 'package:flyinsono/architecture/router/index.dart';
import 'package:flyinsono/architecture/utils/prompt_box.dart';
import 'package:flyinsono/global.dart';
import 'package:fis_common/logger/logger.dart';
import 'package:fis_common/http/http_error.dart';
import 'package:flyinsono/lab/env/env.dart';
import 'package:flyinsono/managers/interfaces/server_config.dart';
import 'package:flyinsono/pages/upgrade/upgrade_widgets/updrade_warpped_dialog.dart';
import 'package:flyinsono/rpc.dart';
import 'package:get/get.dart';

import 'index.dart';

class ServerSettingController extends FControllerBase {
  /// 状态
  final state = ServerSettingState();
  final serverInputController = TextEditingController();

  /// 添加新服务地址
  Future<bool> onAddressAdding() async {
    final formValidateMsg = _validateForm();
    if (formValidateMsg != null) {
      PromptBox.toast(formValidateMsg);
      return false;
    }

    busy = true;

    bool valid = await _checkServerValidation(
      serverInputController.text,
      state.currentPort,
    );
    if (!valid) {
      busy = false;
      PromptBox.toast(i18nBook.setting.serverUrlNotExistValidation.t);
      return false;
    }

    final option = ServerOptionModel(
      name: '${serverInputController.text}:${state.currentPort}',
      host: serverInputController.text,
      port: state.currentPort,
      protocol: state.protocol,
    );
    state.options.add(option);
    onAddressOptionChanged(option);

    /// 缓存服务地址映射
    _syncOptions2Config();
    await Global.config.save();

    busy = false;
    PromptBox.toast(i18nBook.remedical.addSuccess.t);
    return true;
  }

  /// 设置页面添加新的服务地址
  Future<void> onSettingAddressAdding(
    bool? isOpenInSettingPage,
    Function onChangeSettingAddress,
  ) async {
    bool isSuccessAddressAdding = await onAddressAdding();
    if (isSuccessAddressAdding) {
      bool valid = await _checkServerValidation(
        state.currentAddressName,
        state.currentPort,
      );
      // TODO[Baka]: 重构代码结构
      if (isOpenInSettingPage ?? false) onChangeSettingAddress();
      if (valid && (isOpenInSettingPage ?? false)) {
        router.back();
      }
    }
  }

  /// 获取地址选项集合
  Future<List<ServerOptionModel>> onAddressStringChanged(String value) async {
    state.currentAddressName = value;

    if (value.isNullOrWhiteSpace) return state.options.toList();

    final matchList = state.options.where((e) {
      if (e.isDefault) {
        if (e.name.contains(value)) {
          return true;
        }
      }
      if (e.host.contains(value)) {
        return true;
      }
      return false;
    }).toList();
    return matchList;
  }

  /// 处理地址选项删除
  Future<void> onAddressOptionDeleted(ServerOptionModel value) async {
    setBusy(i18nBook.user.deleting.t);
    if (Global.config.data.server.current != DefaultServerName) {
      final currentUri = Global.config.data.server.currentUri!;

      // 不可删除当前正在使用的网络地址
      bool isCurrectNetWork = currentUri.host == value.host &&
          currentUri.port.toString() == value.port;
      // 数据更新
      if (isCurrectNetWork) {
        PromptBox.toast(i18nBook.setting.currentServerAddressInUse.t);
        return;
      }
    }

    final defaultOption = state.options.firstWhere((x) => x.isDefault);
    onAddressOptionChanged(defaultOption);
    // 先切换再删除
    state.options.remove(value);

    _syncOptions2Config();
    _syncHost2Config();
    await Global.config.save();
    if (state.appliedOption.isDefault) {
      // 通知rpc client更新服务地址
      bus.emit(
          bus.Keys.SERVER_ADDRESS_CHANGED,
          state.appliedOption.isDefault
              ? state.appliedOption.uri.toString()
              : state.appliedOption.fullAddress);
    }
    busy = false;
    PromptBox.toast(i18nBook.user.deleteSuccess.t);
    if (FPlatform.isMacOS || FPlatform.isWindows) {
      rpc.platform.reloadConfig();
    }
  }

  /// 处理地址选项变更
  void onAddressOptionChanged(ServerOptionModel value) {
    state.appliedOption = value;
  }

  /// 处理端口变更
  void onPortChanged(String value) {
    state.currentPort = value;
  }

  /// 提交表单
  Future<void> onSubmit() async {
    if (!_checkIsHostChanged()) {
      router.back();
      return PromptBox.toast(i18nBook.setting.serverUrlNotChangedValidation.t);
    }

    setBusy(i18nBook.common.submitting.t);

    _syncHost2Config();
    await Global.config.save();

    //Todo:finlay 服务器地址发生变化推送给盒子
    // var uri = Uri.parse(Global.config.data.server.current!);
    // await CartSystemPlatform.synchServerAddressToSonopost(
    //     uri.host, uri.port.toString());
    // 通知rpc client更新服务地址
    bus.emit(
        bus.Keys.SERVER_ADDRESS_CHANGED,
        state.appliedOption.isDefault
            ? state.appliedOption.uri.toString()
            : state.appliedOption.fullAddress);
    try {
      if (Global.config.data.server.current.isNullOrEmpty ||
          Global.config.data.server.current == DefaultServerName) {
        await Global.initServerSetting();
        logger.i('init flyinsono server end');
      }
    } catch (e) {
      logger.e('ServerSettingController initServerSetting ex:', e);
    }
    Get.find<IServerConfigManager>().getAllServerConfig();
    busy = false;
    router.back();
    router.dialog(
      () => UpgradeWrappedDialog(
        forceCheckUpgrade: true,
      ),
      isShowBarrier: false,
    );
    PromptBox.toast(i18nBook.common.alreadySaved.t);
    if (FPlatform.isMacOS || FPlatform.isWindows) {
      rpc.platform.reloadConfig();
    }
  }

  void _syncHost2Config() async {
    final option = state.appliedOption;
    final url = option.isDefault ? DefaultServerName : option.fullAddress;
    Global.config.data.server.current = url;
    _syncRpcGateway(url);
  }

  void _syncOptions2Config() {
    Global.config.data.server.optionSource = state.options
        .where((e) => !e.isDefault)
        .map((e) => e.fullAddress)
        .toList();
  }

  void _syncRpcGateway(String url) {
    // 通知rpc client更新服务地址
    bus.emit(
        bus.Keys.SERVER_ADDRESS_CHANGED,
        url == DefaultServerName
            ? state.options
                .firstWhere((value) => value.isDefault)
                .uri
                .toString()
            : url);
  }

  @override
  void onInit() {
    super.onInit();
    _loadData();
  }

  void _loadData() {
    List<ServerOptionModel> options = [];
    options = _loadCachedOptions();
    if (kIsLab) {
      var uri = Uri.parse("http://127.0.0.1:8303");
      // 在最前端插入默认选项
      options.insert(
        0,
        ServerOptionModel(
          name: "杏聆荟科研工作站",
          host: uri.host,
          port: uri.port.toString(),
          protocol: uri.scheme,
          isDefault: true,
        ),
      );
    } else {
      var uri = Uri.parse(AppParameters.data.serverGateway);
      // 在最前端插入默认选项
      options.insert(
        0,
        ServerOptionModel(
          name: i18nBook.common.appName.t,
          host: uri.host,
          port: uri.port.toString(),
          protocol: uri.scheme,
          isDefault: true,
        ),
      );
    }

    state.options.addAll(options);
    _loadCachedHost();
  }

  List<ServerOptionModel> _loadCachedOptions() {
    final sercerCfg = Global.config.data.server;
    // 读取选项列表
    final List<ServerOptionModel> options = sercerCfg.optionSource.map((e) {
      String url = e;
      if (e.startsWith("http") == false) {
        url = "http://$e";
      }
      final uri = Uri.parse(url);
      final portStr = uri.hasPort ? ":${uri.port}" : "";
      return ServerOptionModel(
        name: "${uri.host}$portStr",
        host: uri.host,
        port: uri.port.toString(),
        protocol: uri.scheme,
      );
    }).toList();

    return options;
  }

  void _loadCachedHost() {
    final cache = Global.config.data.server;

    try {
      if (cache.currentUri == null && cache.current != DefaultServerName) {
        // 设置默认Server到缓存
        cache.current = AppParameters.data.serverGateway;
      }

      ServerOptionModel matchedOption;
      if (cache.current == DefaultServerName) {
        matchedOption = state.options.firstWhere((value) => value.isDefault);
      } else {
        final uri = cache.currentUri!;
        final address = uri.host;
        final port = uri.port.toString();
        var option = state.options.toList().firstWhereOrNull(
            (e) => e.host == address && e.port == port && !e.isDefault);
        if (option != null) {
          matchedOption = option;
        } else {
          matchedOption = state.options.firstWhere((value) => value.isDefault);
        }
      }
      // 更新选项选中
      state.appliedOption = matchedOption;
    } catch (e) {
      /// 错误处理 新增日志
      // state.appliedOption = state.options.first;
      // _syncHost2Config();
      // Global.config.save();
      logger.e("_loadCachedHost unknown error", e);
    }
  }

  String? _validateForm() {
    final address = serverInputController.text;
    final port = state.currentPort;
    if (address.isEmpty) {
      return i18nBook.setting.FullfillServerUrl.t;
    }
    if (port.isEmpty) {
      return i18nBook.setting.FullfillServerPort.t;
    }
    bool addressMatched = RegExp(
            r'^[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5}(:[0-9]{1,5})?(\/.*)?|^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(:\d{0,5})?(\/.*)?$')
        .hasMatch(serverInputController.text);
    if (!addressMatched) {
      return i18nBook.setting.serverUrlFormatValidation.t;
    }
    bool portMatched = RegExp(
            r'^([0-9]|[1-9]\d{1,3}|[1-5]\d{4}|6[0-4]\d{4}|65[0-4]\d{2}|655[0-2]\d|6553[0-5])$')
        .hasMatch(state.currentPort);
    if (!portMatched) {
      return i18nBook.setting.serverPortFormatValidation.t;
    }
    if (_checkOptionExists(address, port, state.protocol)) {
      return i18nBook.setting.serverUrlExistValidation.t;
    }
    return null;
  }

  bool _checkOptionExists(String address, String port, String protocol) {
    for (var o in state.options) {
      print(o.protocol + (o.isDefault ? o.uri.toString() : o.fullAddress));
    }
    var result = state.options.any(
      (e) =>
          e.host == address &&
          e.port == port &&
          e.protocol == protocol &&
          e.name == "$address:$port",
    );
    return result;
  }

  /// 检查已选服务是否变更
  /// return 是否变更
  bool _checkIsHostChanged() {
    final option = state.appliedOption;
    if (Global.config.data.server.current == DefaultServerName &&
        option.isDefault) {
      return false;
    } else if (Global.config.data.server.current == DefaultServerName &&
        !option.isDefault) {
      return true;
    } else if (Global.config.data.server.current != DefaultServerName &&
        option.isDefault) {
      return true;
    }
    final currentUri = Global.config.data.server.currentUri;
    return option.host != currentUri?.host ||
        option.port != currentUri?.port.toString();
  }

  /// 检验服务有效性
  Future<bool> _checkServerValidation(String address, String port) async {
    try {
      final host = '${state.protocol}://$address:$port';
      var response = await jrpcHttpPool.getClient(
        host,
        timeout: 3000,
        headers: {'content-type': "text/plain"},
      ).post(
        '/ILoginService',
        data:
            '{"jsonrpc":"2.0","method":"CommonLoginAsync","params":[],"id":1}',
      );
      if (response.data != null) {
        print(response.data);
        return true;
      }
    } on FHttpError catch (e) {
      logger.w("check server validation fail. errorType: ${e.type}");
    } catch (e) {
      logger.e("FHttp unknown error", e);
    }
    return false;
  }
}
