// RFC 7807 - Problem Details for HTTP APIs
// https://datatracker.ietf.org/doc/html/rfc7807
// https://raw.githubusercontent.com/PDMLab/http-problem-details/master/src/ProblemDocument.ts

import { httpStatusCodes } from "./HttpStatusCodes";

/**
 * A problem details object can have the following members:

   o  "type" (string) - A URI reference [RFC3986] that identifies the
      problem type.  This specification encourages that, when
      dereferenced, it provide human-readable documentation for the
      problem type (e.g., using HTML [W3C.REC-html5-20141028]).  When
      this member is not present, its value is assumed to be
      "about:blank".

   o  "title" (string) - A short, human-readable summary of the problem
      type.  It SHOULD NOT change from occurrence to occurrence of the
      problem, except for purposes of localization (e.g., using
      proactive content negotiation; see [RFC7231], Section 3.4).

   o  "status" (number) - The HTTP status code ([RFC7231], Section 6)
      generated by the origin server for this occurrence of the problem.

   o  "detail" (string) - A human-readable explanation specific to this
      occurrence of the problem.

   o  "instance" (string) - A URI reference that identifies the specific
      occurrence of the problem.  It may or may not yield further
      information if dereferenced.

 */

export class ProblemDocument {
  public detail?: string;
  public instance?: string;
  public status: number;
  public title: string;
  public type?: string;
  //public status_text: string;

  public constructor(
    options: ProblemDocumentOptions,
    extension?: ProblemDocumentExtension | Record<string, object>
  ) {
    const { title, detail, instance, status } = options;
    let { type } = options;

    if (status && !type) {
      type = "about:blank";
    }

    /*if (instance) {
      // eslint-disable-next-line node/no-deprecated-api
      url.parse(instance);
    }*/

    /*if (type) {
      // eslint-disable-next-line node/no-deprecated-api
      url.parse(type);
      // eslint-disable-next-line node/no-deprecated-api
    }*/

    // const result = {
    this.type = type;

    //if (detail) {
    this.detail = detail;
    //}

    this.instance = instance;
    this.status = Number(status);
    this.title = title ? String(title) : httpStatusCodes[this.status];
    //this.status_text = status ? httpStatusCodes[status] : "";
    // };

    if (extension) {
      const extensionProperties =
        extension instanceof ProblemDocumentExtension
          ? extension.extensionProperties
          : extension;

      for (const propertyName in extensionProperties) {
        if (propertyName in extensionProperties) {
          this[propertyName] = extensionProperties[propertyName];
        }
      }
    }
  }
}

export class ProblemDocumentOptions {
  public detail?: string;
  public instance?: string;
  public type?: string;
  public title?: string;
  public status?: number;
}

export class ProblemDocumentExtension {
  public extensionProperties: Record<string, object>;

  public constructor(extensionProperties: Record<string, object>) {
    this.extensionProperties = extensionProperties;
  }
}
