import type * as servezoneInterfaces from '@serve.zone/interfaces';
import * as interfaces from '../ts_interfaces/index.js';
import type { DcRouterApiClient } from './classes.dcrouterapiclient.js';

export class Certificate {
  private clientRef: DcRouterApiClient;

  // Data from ICertificateInfo
  public domain: string;
  public routeNames: string[];
  public status: interfaces.requests.TCertificateStatus;
  public source: interfaces.requests.TCertificateSource;
  public tlsMode: 'terminate' | 'terminate-and-reencrypt' | 'passthrough';
  public expiryDate?: string;
  public issuer?: string;
  public issuedAt?: string;
  public error?: string;
  public canReprovision: boolean;
  public backoffInfo?: {
    failures: number;
    retryAfter?: string;
    lastError?: string;
  };

  constructor(clientRef: DcRouterApiClient, data: interfaces.requests.ICertificateInfo) {
    this.clientRef = clientRef;
    this.domain = data.domain;
    this.routeNames = data.routeNames;
    this.status = data.status;
    this.source = data.source;
    this.tlsMode = data.tlsMode;
    this.expiryDate = data.expiryDate;
    this.issuer = data.issuer;
    this.issuedAt = data.issuedAt;
    this.error = data.error;
    this.canReprovision = data.canReprovision;
    this.backoffInfo = data.backoffInfo;
  }

  public async reprovision(): Promise<void> {
    const response = await this.clientRef.request<interfaces.requests.IReq_ReprovisionCertificateDomain>(
      'reprovisionCertificateDomain',
      this.clientRef.buildRequestPayload({ domain: this.domain }) as any,
    );
    if (!response.success) {
      throw new Error(response.message || 'Failed to reprovision certificate');
    }
  }

  public async delete(): Promise<void> {
    const response = await this.clientRef.request<interfaces.requests.IReq_DeleteCertificate>(
      'deleteCertificate',
      this.clientRef.buildRequestPayload({ domain: this.domain }) as any,
    );
    if (!response.success) {
      throw new Error(response.message || 'Failed to delete certificate');
    }
  }

  public async export(): Promise<{
    id: string;
    domainName: string;
    created: number;
    validUntil: number;
    privateKey: string;
    publicKey: string;
    csr: string;
  } | undefined> {
    const response = await this.clientRef.request<servezoneInterfaces.requests.gateway.IReq_ExportCertificate>(
      'exportCertificate',
      this.clientRef.buildRequestPayload({ domain: this.domain }) as any,
    );
    if (!response.success) {
      throw new Error(response.message || 'Failed to export certificate');
    }
    return response.cert;
  }
}

export interface ICertificateSummary {
  total: number;
  valid: number;
  expiring: number;
  expired: number;
  failed: number;
  unknown: number;
}

export class CertificateManager {
  private clientRef: DcRouterApiClient;

  constructor(clientRef: DcRouterApiClient) {
    this.clientRef = clientRef;
  }

  public async list(): Promise<{ certificates: Certificate[]; summary: ICertificateSummary }> {
    const response = await this.clientRef.request<interfaces.requests.IReq_GetCertificateOverview>(
      'getCertificateOverview',
      this.clientRef.buildRequestPayload() as any,
    );
    return {
      certificates: response.certificates.map((c) => new Certificate(this.clientRef, c)),
      summary: response.summary,
    };
  }

  public async import(cert: {
    id: string;
    domainName: string;
    created: number;
    validUntil: number;
    privateKey: string;
    publicKey: string;
    csr: string;
  }): Promise<void> {
    const response = await this.clientRef.request<servezoneInterfaces.requests.gateway.IReq_ImportCertificate>(
      'importCertificate',
      this.clientRef.buildRequestPayload({ cert }) as any,
    );
    if (!response.success) {
      throw new Error(response.message || 'Failed to import certificate');
    }
  }
}
