import { faker } from '@faker-js/faker'
import { DataCatalogKind, DataCatalogVersionKind } from '../../models/kinds.js'
import { nanoid } from '../../nanoid.js'
import type {
  DataCatalogSchemaWithVersion,
  DataCatalogSchema,
  DataCatalogScope,
  DataCatalogVersionInfo,
} from '../../models/DataCatalog.js'
import type { DataCatalogLifecycle, DataCatalogVersionSchema } from '../../models/DataCatalogVersion.js'

const dataCatalogScopes: DataCatalogScope[] = ['public', 'private', 'organization'] as const
const dataCatalogLifecycles: DataCatalogLifecycle[] = ['stable', 'beta', 'dev'] as const

export class DataCatalog {
  /**
   * Generates a random data catalog object.
   * @param init Optional values to be present in the object.
   * @returns Random data catalog object.
   */
  dataCatalog(init: Partial<DataCatalogSchema> = {}): DataCatalogSchema {
    const {
      key = nanoid(),
      organization = nanoid(),
      file = nanoid(),
      scope = faker.helpers.arrayElement(dataCatalogScopes),
      name = faker.company.name(),
      description = faker.lorem.sentence(),
      publishedBy = nanoid(),
      publishedAt = faker.date.past().getTime(),
      createdAt = faker.date.past().getTime(),
      updatedAt = faker.date.recent().getTime(),
      tags = faker.helpers.uniqueArray(faker.lorem.word, 3),
    } = init
    return {
      kind: DataCatalogKind,
      key,
      name,
      organization,
      file,
      createdAt,
      updatedAt,
      scope,
      description,
      publishedBy,
      publishedAt,
      tags,
    }
  }

  /**
   * Generates a list of random data catalog objects.
   * @param size Number of data catalogs to generate. Default is 25.
   * @returns List of random data catalogs
   */
  dataCatalogs(size = 25): DataCatalogSchema[] {
    const result = []
    for (let i = 0; i < size; i++) {
      result.push(this.dataCatalog())
    }
    return result
  }

  /**
   * Generates a random data catalog version object.
   * @param init Optional values to be present in the object.
   * @returns Random data catalog version object.
   */
  dataCatalogVersion(init: Partial<DataCatalogVersionSchema> = {}): DataCatalogVersionSchema {
    const {
      key = nanoid(),
      catalogKey = nanoid(),
      scope = faker.helpers.arrayElement(dataCatalogScopes),
      lifecycle = faker.helpers.arrayElement(dataCatalogLifecycles),
      version = 'v' + faker.system.semver(),
      publishedBy = nanoid(),
      createdAt = faker.date.past().getTime(),
      updatedAt = faker.date.recent().getTime(),
      changelog = faker.lorem.paragraph(),
    } = init
    return {
      kind: DataCatalogVersionKind,
      key,
      catalogKey,
      scope,
      lifecycle,
      version,
      publishedBy,
      createdAt,
      updatedAt,
      changelog,
    }
  }

  /**
   * Generates a list of random data catalog version objects.
   * @param size Number of data catalog versions to generate. Default is 25.
   * @returns List of random data catalog versions.
   */
  dataCatalogVersions(size = 25): DataCatalogVersionSchema[] {
    const result = []
    for (let i = 0; i < size; i++) {
      result.push(this.dataCatalogVersion())
    }
    return result
  }

  /**
   * Generates a random data catalog object with versions.
   * @param init Optional values to be present in the object.
   * @returns Random data catalog object with versions.
   */
  dataCatalogWithVersion(init: Partial<DataCatalogSchemaWithVersion> = {}): DataCatalogSchemaWithVersion {
    const result = this.dataCatalog(init) as DataCatalogSchemaWithVersion
    const versionsSize = faker.number.int({ min: 1, max: 20 })
    const versions = []
    for (let i = 0; i < versionsSize; i++) {
      versions.push({
        version: `v${i + 1}.0.0`,
        lifecycle: faker.helpers.arrayElement(dataCatalogLifecycles),
      })
    }
    result.versions = versions
    return result
  }

  /**
   * Generates a list of random data catalog objects with versions.
   * @param size Number of data catalogs to generate. Default is 3.
   * @returns List of random data catalogs with versions.
   */
  dataCatalogsWithVersion(size = 3): DataCatalogSchemaWithVersion[] {
    const result = []
    for (let i = 0; i < size; i++) {
      result.push(this.dataCatalogWithVersion())
    }
    return result
  }

  /**
   * Generates a random data catalog version info object.
   * @param init Optional values to be present in the object.
   * @returns Random data catalog version info object.
   */
  versionInfo(init: Partial<DataCatalogVersionInfo> = {}): DataCatalogVersionInfo {
    const { key = nanoid(), version = 'v' + faker.system.semver(), published = faker.date.past().getTime() } = init
    return {
      key,
      version,
      published,
    }
  }

  /**
   * Generates a list of random data catalog version info objects.
   * @param size Number of data catalog version info objects to generate. Default is 5.
   * @returns List of random data catalog version info objects.
   */
  versionInfos(size = 5): DataCatalogVersionInfo[] {
    const result = []
    for (let i = 0; i < size; i++) {
      result.push(this.versionInfo())
    }
    return result
  }
}
