//Use File System as DB storage
import fs from 'fs';
import { AuditRecord, AuditEngine, PNRESETTYPES } from '../../interfaces/index.js';
import protocol from './protocol.js';
import sequence from './sequence.js';

/**
 * @description AuditEngine implementation
 * @note This class is used to implement the methods that must be implemented by the AuditEngine
 * @class FileEngine
 * @implements AuditEngine
 * @param {string} path - path to store the records
 * @param {PNRESETTYPES} pnreset - protocol number sequence type
 */
export class FileEngine implements AuditEngine {
  #path: string
  #pnreset:PNRESETTYPES

  constructor(path?: string, pnreset?: PNRESETTYPES) {
    this.#path = path?path:"/tmp";
    this.#pnreset = pnreset || "innumerable";
  }

  /**
   * @description Store a record in the database
   * @param {AuditRecord} record - record to be stored
   * @returns {AuditRecord} - the record stored
   * @memberof FileEngine
   * @method put
   */
  put(record: AuditRecord): AuditRecord {
    const data = JSON.stringify(record, null, 2);
    try {
      fs.writeFileSync(this.#path + '/record-' + record.auditTransactionId + '.json', data);
      return record;
    } catch (error) {
      throw error;
    }
  }
  
  /**
   * @description Get a record from the database
   * @param auditTransactionId 
   * @returns {AuditRecord}
   * @memberof FileEngine
   * @method get
   */
  get(auditTransactionId: string): AuditRecord {
    try {
      const data = fs.readFileSync(this.#path + '/record-' + auditTransactionId + '.json', 'utf8');
      return JSON.parse(data);
    } catch (error) {
      throw error;
    }
  }

  /**
   * @description Generate a new sequence number
   * @param path
   * @returns number
   * @memberof FileEngine
   * @method seq
   */
  seq(path?: string): number {
    const sequence_save_path = path || this.#path;
    try {
      return sequence(sequence_save_path + "/sequence", sequence_save_path + "/sequence")
    } catch (error) {
      throw error;
    }
  }

  /**
   * @description Generate a new protocol number
   * @param type: SEQTYPES
   * @param path: string
   * @returns string
   * @memberof FileEngine
   * @method protocol
   */
  pn(reset?:PNRESETTYPES, path?: string): string {
    const protocol_save_path = path || this.#path;
    const protocol_reset = reset || this.#pnreset;
    try {
      return protocol(protocol_save_path,protocol_reset)
    } catch (error) {
      throw error;
    }
  }
}

export default FileEngine;