import { Eureka, EurekaClient } from 'eureka-js-client';
const address = require("address")

import client from './client';
import Pool from './pool';
import { sleep } from './utils';

interface IEureka {
  port: number;
  appName: string;
  services: string[];
}

let NODE_ENV = process.env.NODE_ENV || 'dev';

export default class Eurekaclient {
  private eureka: Eureka;
  private opts: IEureka;
  private pool: Pool;
  constructor(options: IEureka) {
    options.services.push(options.appName);
    this.opts = options;
    this.eureka = client(options);
    this.pool = new Pool(this.eureka, this.opts.services);
  }

  /**
   * 启动eureka
   * @returns Promise<Eureka>
   */
  async start() {
    const { opts, eureka } = this;
    if (NODE_ENV) eureka.start()

    await sleep(5000)
    // 如果是生产环境,开启服务掉线校验
    this.checkServiceHasNeedRegistry(opts.appName)
  }

  /**
   * stop
   */
  stop() {
    this.eureka.stop();
  }

  /**
   * 获取指定应用的ip
   * @param {(string | number)} name 应用名
   * @param {(string)} localIp 客户端IP
   * @param {string} [filterGroup] 要过滤的group service
   */
  getHost(name: string | number, localIp: string, filterGroup?: string) {
    if (!NODE_ENV) {
      const ip = address.ip();
      return `http://${ip}:${this.opts.port}`
    }
    return this.pool.getHost(name, localIp, filterGroup)
  }

  /** 获取代理信息(客户端IP, serviceGroupKey) */
  getProxyInfoFromReq(req: any) {
    const name = '_duibaServiceGroupKey';
    const reg = new RegExp("(^| )" + name + "=([^;]*)(;|$)");

    // 获取多场景的cookie
    let arr = [];
    let serviceGroupKey = ''
    if (req.headers.cookie && (arr = req.headers.cookie.match(reg))) {
      serviceGroupKey = unescape(arr[2]);
    }

    // 获取客户端ip地址
    let ip = req.headers['x-real-ip'] || req.headers['x-forwarded-for'] || req.connection.remoteAddres || req.socket.remoteAddress || '';

    if (ip.indexOf('::ffff:') !== -1) {
      ip = ip.substring(7);
    }
    return { ip, serviceGroupKey }
  }
  /**
   * 获取所有eureka
   */
  getAllEurekas(): EurekaClient.EurekaInstanceConfig[] {
    return this.pool.getAllEurekas();
  }

  /**
   * 获取所有实例下的host
   */
  getAllHostName() {
    return this.pool.getAllHostName();
  }

  /**
   * 检查eureka服务是否掉线，掉线则重新注册服务
   * @param {string} appName
   * @memberof Eurekaclient
   */
  checkServiceHasNeedRegistry(appName: string) {
    let timer = null

    // 服务开始注册后1分钟启动监听，每隔10s检查该服务是否不存在，如不存在重新注册
    timer = setInterval(async () => {
      const instances = await this.eureka.getInstancesByAppId(appName);
      if (instances?.length === 0) {
        console.log('服务出错')
        global['Log']?.error(`eureka`, `${appName} 服务掉线`)
        clearInterval(timer)
        await this.eureka.start()
        global['Log']?.error(`eureka`, `${appName} 重新注册`)
        await sleep(10000)
        this.checkServiceHasNeedRegistry(appName)
      }
    }, 10000)
  }
}
