import 'dart:io';
import 'dart:async';
import 'dart:convert';

import 'package:get/get.dart';
import 'package:naiyouwl/app/bean/ClashServiceInfo.dart';
import 'package:naiyouwl/app/clash/service/clash_service.dart';
import 'package:naiyouwl/app/const/const.dart';
import 'package:naiyouwl/app/controller/controllers.dart';
import 'package:naiyouwl/app/utils/logger.dart';
import 'package:naiyouwl/app/utils/shell.dart';

import 'package:path/path.dart' as path;
import 'package:http/http.dart' as http;

import '../clash/mode/clash_config.dart';
import '../common/constants.dart';
import '../utils/utils.dart';

final headers = {"User-Agent": "ccore-for-flutter/0.0.1"};

class ServiceController extends GetxController {

  var url = "";
  var client = http.Client();
  var serviceMode = false.obs;
  var coreStatus = RunningState.stoped.obs;
  var serviceStatus = RunningState.stoped.obs;
  var installStatus = false.obs; // 新增变量用于记录安装/卸载状态
  bool get serviceIsRuning => serviceStatus.value == RunningState.running;
  bool get coreIsRuning => coreStatus.value == RunningState.running;

  Future<void> initConfig() async{
    url = "127.0.0.1:${controllers.config.config.value.servicePort}";
    //controllers.config.setSerivcePort(controllers.config.config.value.servicePort);
  }

  Future<void> startTunService() async {
    try {
      while (true) {
        final data = await fetchInfo() ?? ClashServiceInfo.fromJson({'code': -1, 'mode': '', 'status': '-1', 'version': '-1'});
        if (data.mode != 'service-mode') {
          if (serviceStatus.value == RunningState.running) {
            await stopService();
          }
          await install();
        } else {
          break;
        }
      }
    } catch (e) {
      serviceStatus.value = RunningState.error;
      log.debug(e.toString());
    }
  }

  Future<ClashServiceInfo?> fetchInfo() async {
    try {
      final res = await client.post(Uri.http(url, 'info'), headers: headers);
      var jsonResponse = jsonDecode(res.body) as Map<String, dynamic>;
      return ClashServiceInfo.fromJson(jsonResponse);
    } catch (e) {
      print('Exception: $e');
      return null;
    }
  }

  Future<void> fetchStartInit() async {
    await controllers.service.makeInitConfig();
    controllers.config.config.value.selected = Files.makeInitProxyConfig.path;
    controllers.global.updateMsg("服务模式初始化...");
    await fetchStop();

    try {
      var ut = Uri.http(url, 'start');
      final body = json.encode({
        "coreName": Files.assetsCCore.path,
        "args": [
          '-d',
          Paths.config.path,
          '-f',
          path.join(Paths.config.path, controllers.config.config.value.selected)
        ]
      });
      final res = await client.post(ut, body: body, headers: headers);
      var jsonResponse = jsonDecode(res.body) as Map<String, dynamic>;
      if (jsonResponse["code"] != 0) {
        coreStatus.value = RunningState.error;
        throw jsonResponse["msg"];
      }
      controllers.global.updateMsg("服务模式初始化成功..");
      coreStatus.value = RunningState.running;
    } catch (e) {
      print('Exception: $e');
      coreStatus.value = RunningState.error;
      controllers.global.updateMsg("服务模式初始化失败..");
    }
  }
 //应该程序退出调用
  Future<void> fetchStop() async {
    try {
      var ut = Uri.http(url, 'stop');
      await client.post(ut, headers: headers);
      coreStatus.value = RunningState.stoped;
    } catch (e) {
      print('Exception: $e');
    }
  }

  Future<void> fetchSetProxy() async {
    try {
      var dns_ip = "";
      if (controllers.global.routeModesSelect.value == "tun") {
        dns_ip = "198.18.0.2";
      }
      var ut = Uri.http(url, 'on');
      final body = json.encode({
        "http_port": controllers.config.mixedPort.value,
        "https_port": controllers.config.mixedPort.value,
        "socks_port": controllers.config.mixedPort.value,
        "bypass": "127.0.0.1, 192.168.0.0/16, 10.0.0.0/8, 172.16.0.0/12, 100.64.0.0/10, 17.0.0.0/8, localhost, *.local, *.crashlytics.com, seed-sequoia.siri.apple.com, sequoia.apple.com,xd.apple.com",
        "dns_ip": dns_ip,
        "dns_type": "",
        "address": "127.0.0.1"
      });
      await client.post(ut, body: body, headers: headers);
    } catch (e) {
      print('Exception: $e');
    }
  }

  Future<void> fetchSetProxyStop() async {
    try {
      var dnsIp = "";
      if (controllers.global.routeModesSelect.value == "tun") {
        dnsIp = "223.5.5.5";
      }
      var ut = Uri.http(url, 'off');
      final body = json.encode({
        "bypass": "",
        "dns_ip": dnsIp
      });
      await client.post(ut, body: body, headers: headers);
    } catch (e) {
      print('Exception: $e');
    }
  }

  Future<void> waitServiceStart() async {
    while (true) {
      await Future.delayed(const Duration(milliseconds: 100));
      try {
        await isCanOperationService();
        break;
      } catch (_) {}
    }
  }

  Future<void> install() async {
    try {
      final res = await runAsAdmin(Files.assetsClashService.path, ["-port", "${controllers.config.config.value.servicePort}", "stop", "uninstall", "install", "start"]);

      log.debug('install', res.stdout, res.stderr);

      if (res.exitCode != 0) {

        throw res.stderr;
      }

      await waitServiceStart();
      serviceStatus.value = RunningState.running;

      if (serviceStatus.value == RunningState.running) {
        await controllers.service.stopClashCore();
        await Future.delayed(Duration(seconds: 3));
        await fetchStartInit();
      }

      installStatus.value = true; // 安装成功
    } catch (e) {
      installStatus.value = false; // 安装失败
      log.debug('安装失败: $e');
      throw e;
    }
  }

  Future<void> uninstall() async {
    try {
      serviceStatus.value = RunningState.uninstall;
      final res = await runAsAdmin(Files.assetsClashService.path, ["stop", "uninstall"]);
      log.debug('uninstall', res.stdout, res.stderr);
      if (res.exitCode != 0) throw res.stderr;
      installStatus.value = false; // 卸载成功
      await Future.delayed(Duration(seconds: 2));
      // final conn = await controllers.core.fetchConnection();
      // if(conn != null)
      // {
      //   for (final it in conn.connections) {
      //     await controllers.core.fetchCloseConnections(it.id);
      //   }
      // }
      await controllers.service.updatePorts();
      await Future.delayed(Duration(seconds: 2));
      await controllers.service.makeInitConfig();
      await Future.delayed(Duration(seconds: 5));
      await controllers.service.startClashCore();

      serviceStatus.value = RunningState.stoped;

    } catch (e) {
      installStatus.value = true; // 卸载失败
      log.debug('卸载失败: $e');

      throw e;
    }
  }

  Future<void> stopService() async {
    serviceStatus.value = RunningState.stopping;
    if (coreStatus.value == RunningState.running) await fetchStop();
    serviceStatus.value = RunningState.stoped;
  }

  Future<void> serviceModeSwitch(bool open) async {

   // if (serviceStatus.value == RunningState.running) await controllers.service.stopClashCore();
    // if (serviceStatus.value == RunningState.running) await fetchStop();
    serviceStatus.value = RunningState.starting;
    try {
      controllers.global.updateMsg(open ? "安装服务" : "卸载服务");
      open ? await install() : await uninstall();

    } catch (e) {
      print(e.toString());
    }
    if(open)
    {
      await fetchStartInit();
    }
  }

  Future<void> stopClash() async {
    controllers.config.config.value.selected = Files.makeInitProxyConfig.path;
    if (coreStatus.value == RunningState.running) {
      await controllers.config.readClashCoreApi();
      controllers.core.setApi(controllers.config.clashCoreApiAddress.value, controllers.config.clashCoreApiSecret.value);
      await controllers.core.changeConfig(path.join(Paths.config.path, controllers.config.config.value.selected));
    }
  }

  Future<void> reloadClashCore() async {
    try {
      controllers.config.config.value.selected = Files.makeProxyConfig.path;
      if (coreStatus.value == RunningState.running) {
        controllers.global.updateMsg("切换配置...");
        await controllers.config.readClashCoreApi();
        controllers.core.setApi(controllers.config.clashCoreApiAddress.value, controllers.config.clashCoreApiSecret.value);
        await controllers.core.changeConfig(path.join(Paths.config.path, controllers.config.config.value.selected));
        controllers.global.updateMsg("fetchReloadConfig${controllers.config.clashCoreApiAddress.value}...");
      }
    } catch (e) {




      controllers.global.updateMsg("重新配置...");
      await controllers.config.readClashCoreApi();
      controllers.core.setApi(controllers.config.clashCoreApiAddress.value, controllers.config.clashCoreApiSecret.value);
      await controllers.core.changeConfig(path.join(Paths.config.path, controllers.config.config.value.selected));
    }
  }

  Future<bool> isCanOperationService() async {
    try {
      final res = await client.post(Uri.http(url, 'info'), headers: headers);
      if(res.statusCode == 200)
      {
        serviceStatus.value = RunningState.running;
      }

      return installStatus.value = res.statusCode == 200;
    } catch (e) {

      serviceStatus.value = RunningState.stoped;
      installStatus.value = false;
      return false;
      print('Exception when checking service: $e');
      return false;
    }
  }

  Future<bool> isClashCoreRunning() async {
    try {
      final res = await client.post(Uri.http(url, 'info'), headers: headers);
      if (res.statusCode == 200) {
        var jsonResponse = jsonDecode(res.body) as Map<String, dynamic>;
        return jsonResponse['status'] == 'running';
      }
      return false;
    } catch (e) {
      print('Exception when checking Clash core: $e');
      return false;
    }
  }



}
