import { IDomainParser, ISubDomainsGetter } from "./api";
//@ts-ignore
import psl from "psl";
import { ILogger, utils, logger as globalLogger } from "@certd/basic";
import { resolveDomainBySoaRecord } from "@certd/acme-client";

export class DomainParser implements IDomainParser {
  subDomainsGetter: ISubDomainsGetter;
  logger: ILogger;
  constructor(subDomainsGetter: ISubDomainsGetter, logger?: ILogger) {
    this.subDomainsGetter = subDomainsGetter;
    this.logger = logger || globalLogger;
  }

  parseDomainByPsl(fullDomain: string) {
    const parsed = psl.parse(fullDomain) as psl.ParsedDomain;
    if (parsed.error) {
      throw new Error(`解析${fullDomain}域名失败:` + JSON.stringify(parsed.error));
    }
    return parsed.domain as string;
  }

  async parse(fullDomain: string) {
    this.logger.info(`查找主域名:${fullDomain}`);
    const cacheKey = `domain_parse:${fullDomain}`;
    const value = utils.cache.get(cacheKey);
    if (value) {
      this.logger.info(`从缓存获取到主域名:${fullDomain}->${value}`);
      return value;
    }

    const subDomains = await this.subDomainsGetter.getSubDomains();
    if (subDomains && subDomains.length > 0) {
      const fullDomainDot = "." + fullDomain;
      for (const subDomain of subDomains) {
        if (fullDomainDot.endsWith("." + subDomain)) {
          //找到子域名托管
          utils.cache.set(cacheKey, subDomain, {
            ttl: 60 * 1000,
          });
          this.logger.info(`获取到子域名托管域名:${fullDomain}->${subDomain}`);
          return subDomain;
        }
      }
    }

    const res = this.parseDomainByPsl(fullDomain);
    this.logger.info(`从psl获取主域名:${fullDomain}->${res}`);

    let soaManDomain = null;
    try {
      const mainDomain = await resolveDomainBySoaRecord(fullDomain);
      if (mainDomain) {
        this.logger.info(`从SOA获取到主域名:${fullDomain}->${mainDomain}`);
        soaManDomain = mainDomain;
      }
    } catch (e) {
      this.logger.error("从SOA获取主域名失败", e.message);
    }
    if (soaManDomain && soaManDomain !== res) {
      this.logger.warn(`SOA获取的主域名（${soaManDomain}）和psl获取的主域名(${res})不一致，请确认是否有设置子域名托管`);
    }

    return res;
  }
}
