import path from 'path';

import fs from 'fs-extra';
import yaml from 'yaml';
import _ from 'lodash';

import environment from '../environment.ts';
import util from '../util.ts';

const CONFIG_PATH = path.join(path.resolve(), 'configs/', environment.env, "/service.yml");

/**
 * 服务配置
 */
export class ServiceConfig {

    /** 服务名称 */
    name: string;
    /** @type {string} 服务绑定主机地址 */
    host;
    /** @type {number} 服务绑定端口 */
    port;
    /** @type {string} 服务路由前缀 */
    urlPrefix;
    /** @type {string} 服务绑定地址（外部访问地址） */
    bindAddress;
    /** 数据库配置 */
    database?: {
        mongodb?: {
            url: string;
        };
    };
    // 心跳服务已移除

    constructor(options?: any) {
        const { name, host, port, urlPrefix, bindAddress, database } = options || {};
        this.name = _.defaultTo(name, 'jimeng-free-api');
        this.host = _.defaultTo(host, '0.0.0.0');
        this.port = _.defaultTo(port, 5566);
        this.urlPrefix = _.defaultTo(urlPrefix, '');
        this.bindAddress = bindAddress;
        this.database = database;
        // 心跳服务已移除
    }

    get addressHost() {
        if(this.bindAddress) return this.bindAddress;
        const ipAddresses = util.getIPAddressesByIPv4();
        for(let ipAddress of ipAddresses) {
            if(ipAddress === this.host)
                return ipAddress;
        }
        return ipAddresses[0] || "127.0.0.1";
    }

    get address() {
        return `${this.addressHost}:${this.port}`;
    }

    get pageDirUrl() {
        return `http://127.0.0.1:${this.port}/page`;
    }

    get publicDirUrl() {
        return `http://127.0.0.1:${this.port}/public`;
    }

    static load() {
        // 从环境变量获取配置，支持 PM2 和其他方式设置的环境变量
        const external = _.pickBy({
            name: environment.name,
            host: environment.host,
            port: environment.port || (process.env.PORT ? Number(process.env.PORT) : undefined) // 支持 PM2 的 PORT 环境变量
        }, (v, k) => !_.isUndefined(v));
        
        if(!fs.pathExistsSync(CONFIG_PATH)) return new ServiceConfig(external);
        const data = yaml.parse(fs.readFileSync(CONFIG_PATH).toString());
        return new ServiceConfig({ ...data, ...external });
    }

}

export default ServiceConfig.load();