import { faker } from '@faker-js/faker'
import { nanoid } from '../../nanoid.js'
import {
  IPermission,
  Kind as PermissionKind,
  type PermissionRole,
  type PermissionType,
  type PermissionSourceRule,
} from '../../models/store/Permission.js'

export class Permission {
  /**
   * Generates a random permission object.
   * @param init Configuration options for the permission object.
   * @returns Random permission
   */
  permission(init: Partial<IPermission> = {}): IPermission {
    const type = init.type ?? faker.helpers.arrayElement(['user', 'group', 'organization'] as PermissionType[])
    const role = init.role ?? faker.helpers.arrayElement(['reader', 'commenter', 'writer', 'owner'] as PermissionRole[])

    const result: IPermission = {
      kind: PermissionKind,
      key: init.key ?? nanoid(),
      type,
      granteeId: init.granteeId ?? nanoid(),
      itemId: init.itemId ?? nanoid(),
      role,
      addingUser: init.addingUser ?? nanoid(),
      depth: init.depth ?? 0,
      sourceRule:
        init.sourceRule ??
        faker.helpers.arrayElement([
          'direct_user_grant',
          'creator_default_owner',
          'parent_owner_editor_rule',
        ] as PermissionSourceRule[]),
    }

    if ('displayName' in init) {
      result.displayName = init.displayName
    } else {
      if (type === 'user') {
        result.displayName = faker.person.fullName()
      } else if (type === 'group') {
        result.displayName = faker.lorem.word()
      } else if (type === 'organization') {
        result.displayName = faker.company.name()
      }
    }

    if ('expirationTime' in init) {
      result.expirationTime = init.expirationTime
    } else if (type === 'user' || type === 'group') {
      result.expirationTime = faker.date.future().getTime()
    }

    return result
  }

  /**
   * Generates a random user permission object.
   * @param init Configuration options for the permission object.
   * @returns Random user permission
   */
  userPermission(init: Partial<IPermission> = {}): IPermission {
    return this.permission({ ...init, type: 'user' })
  }

  /**
   * Generates a random group permission object.
   * @param init Configuration options for the permission object.
   * @returns Random group permission
   */
  groupPermission(init: Partial<IPermission> = {}): IPermission {
    return this.permission({ ...init, type: 'group' })
  }

  /**
   * Generates a random organization permission object.
   * @param init Configuration options for the permission object.
   * @returns Random organization permission
   */
  organizationPermission(init: Partial<IPermission> = {}): IPermission {
    return this.permission({ ...init, type: 'organization' })
  }

  /**
   * Generates a list of random permission objects.
   * @param size The size of the returning array. Default is 25.
   * @param init Configuration options for the permission object.
   * @returns List of random permissions
   */
  permissions(size = 25, init: Partial<IPermission> = {}): IPermission[] {
    const result: IPermission[] = []
    for (let i = 0; i < size; i++) {
      result.push(this.permission(init))
    }
    return result
  }
}
