"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateIdTracker = generateIdTracker;
function generateIdTracker(context) {
    return `
import { yellow } from '@postxl/utils'

type WithId = { id: string }

/**
 * Type guard to check if an object has an 'id' property
 */
const hasId = <T extends object>(x: T): x is T & WithId => x && Object.prototype.hasOwnProperty.call(x, 'id')

/**
 * A utility class to generate and track unique ids for objects
 */
export class ${context.mockData.idTracker.name}<_T extends object> {
  private lastId = -1
  private readonly usedIds = new Set<number>()
  constructor(private readonly idPrefix: string) {}

  /**
   * Assert that the given object has an 'id' property
   * If the object does not have an 'id' property, generate a new id using the idPrefix
   * If the object has an 'id' property, track it and ensure it is unique
   */
  public assertId<U extends object>(obj: U): asserts obj is U & WithId {
    if (hasId(obj)) {
      // Track the id of the object
      this.trackId(obj)
    } else {
      // Generate a new id using the idPrefix
      ;(obj as any).id = this.generateId(this.idPrefix)
    }
  }

  /**
   * Generate a unique id based on the idPrefix by appending a number to it
   * For example, if the idPrefix is 'post' and the lastId is 3, the generated id should be 'post4'
   */
  private generateId(idPrefix: string): string {
    // Add the lastId to the usedIds set for tracking
    this.usedIds.add(++this.lastId)
    return \`\${idPrefix}\${this.lastId}\`
  }

  /**
   * Track the id of given object by extracting the prefix and numeric part of the id
   * It checks to see if the prefix part is the same as the idPrefix
   * If the id has the same prefix, the numeric part of the id will be used to update the lastId
   * so that the next generated id will be unique
   */
  private trackId<U extends object>(obj: U): U & WithId {
    if (hasId(obj)) {
      // Extract the prefix and numeric part of the id using a regular expression
      // ** For example, if the id is 'post4', match[0] will be 'post4', match[1] will be 'post', and match[2] will be '4'
      // ** If the id is '1country22', match[0] will be '1country22', match[1] will be '1country', and match[2] will be '22'
      // If the prefix part of the id is the same as the idPrefix, proceed to track the id
      // If the prefix part of the id is not the same as the idPrefix, we keep the id as is and skip tracking
      // Note: Using [^\\d]* instead of .*? to avoid ReDoS vulnerability

      const match = obj.id.match(/^([^\\d]*)(\\d*)$/)
      const extractedPrefix = match ? match[1] : ''

      // Check if the extracted prefix matches the idPrefix (case-insensitive)
      if (extractedPrefix.toLocaleLowerCase() === this.idPrefix.toLocaleLowerCase()) {
        const extractedNumeric = match && match[2] ? match[2] : null
        // Parse the numeric part as an integer
        const numericId = extractedNumeric ? Number.parseInt(extractedNumeric, 10) : NaN

        // Check if numericId is a valid number
        if (!Number.isNaN(numericId)) {
          // If numericId is greater than lastId, update lastId and add numericId to usedIds
          if (numericId > this.lastId) {
            this.lastId = numericId
            this.usedIds.add(numericId)
          } else {
            // Check if numericId is not already in usedIds
            if (!this.usedIds.has(numericId)) {
              // Add numericId to usedIds
              this.usedIds.add(numericId)
            } else {
              // If numericId is already in usedIds, generate a new id using the extracted prefix
              console.log(
                \`\${yellow(\`!!! Warning\`)} {\${JSON.stringify(obj)}}, id \${obj.id} is already used, generating new id ...\`,
              )
              ;(obj as any).id = this.generateId(extractedPrefix)
              console.log(\`\${yellow('New id: ' + obj.id)}, will be used instead\`)
            }
          }
        }
      }
    }

    return obj as U & WithId
  }
}
  `;
}
//# sourceMappingURL=id-tracker.generator.js.map