import { GroupKind } from '../kinds.js'
import type { IDeletion } from './Deletion.js'
import { nanoid } from '../../nanoid.js'

/**
 * @deprecated Use `GroupSchema` instead.
 * This interface is kept for backward compatibility.
 */
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
export interface IGroup extends GroupSchema {}

/**
 * An object representing a user group.
 */
export interface GroupSchema {
  kind: typeof GroupKind
  /**
   * The key of the group.
   * If not provided, it will be generated automatically by the API
   */
  key: string
  /**
   * The name of the group.
   * This is a required field and must be unique within the organization.
   * @required
   */
  name: string
  /**
   * The description of the group.
   */
  description?: string
  /**
   * The id of the user that created this group.
   * This field is ignored by the API and is set automatically.
   * @readonly
   */
  owner: string
  /**
   * The icon of the group, if any.
   * An optional icon for the group, stored as a URL or path.
   * Max 255 characters.
   */
  icon?: string
  /**
   * The color of the group, if any.
   * An optional color for the group, stored as a hex code.
   * Max 50 characters (including the #).
   */
  color?: string
  /**
   * The organization ID this group belongs to.
   * This field is ignored by the API and is set automatically.
   * @readonly
   */
  oid: string
  /**
   * The list of users in this group.
   * This field is ignored by the API and is set automatically.
   * @readonly
   */
  users: string[]
  /**
   * Describes when this group was created
   * This field is ignored by the API and is set automatically.
   * @readonly
   */
  createdAt: number
  /**
   * Describes when this group was updated
   * This field is ignored by the API and is set automatically.
   * @readonly
   */
  updatedAt: number
  /**
   * Optional deletion information if the group has been deleted.
   * This field is ignored by the API and is set automatically.
   * @readonly
   */
  deleteInfo?: IDeletion
}

export class Group implements GroupSchema {
  kind: typeof GroupKind = GroupKind
  key = ''
  name = ''
  description?: string
  owner = ''
  icon?: string
  color?: string
  oid = ''
  users: string[] = []
  createdAt = 0
  updatedAt = 0
  deleteInfo?: IDeletion

  static createSchema(input: Partial<GroupSchema> = {}): GroupSchema {
    const { key = nanoid() } = input
    const result: GroupSchema = {
      kind: GroupKind,
      key,
      name: input.name || 'Unnamed group',
      oid: input.oid || '',
      owner: input.owner || '',
      users: input.users || [],
      createdAt: input.createdAt || Date.now(),
      updatedAt: input.updatedAt || Date.now(),
    }
    if (input.description) {
      result.description = input.description
    }
    if (input.icon) {
      result.icon = input.icon
    }
    if (input.color) {
      result.color = input.color
    }
    if (input.deleteInfo) {
      result.deleteInfo = input.deleteInfo
    }
    return result
  }

  static fromName(name: string, oid: string): Group {
    return new Group({ name, oid })
  }

  constructor(state?: Partial<GroupSchema>) {
    const init = Group.createSchema(state)
    this.key = init.key
    this.name = init.name
    this.description = init.description
    this.owner = init.owner
    this.icon = init.icon
    this.color = init.color
    this.oid = init.oid
    this.users = init.users
    this.createdAt = init.createdAt
    this.updatedAt = init.updatedAt
    this.deleteInfo = init.deleteInfo
  }

  toJSON(): GroupSchema {
    const result: GroupSchema = {
      kind: this.kind,
      key: GroupKind,
      name: this.name,
      oid: this.oid,
      owner: this.owner,
      users: [...this.users],
      createdAt: this.createdAt,
      updatedAt: this.updatedAt,
    }
    if (this.description) {
      result.description = this.description
    }
    if (this.icon) {
      result.icon = this.icon
    }
    if (this.color) {
      result.color = this.color
    }
    if (this.deleteInfo) {
      result.deleteInfo = { ...this.deleteInfo }
    }
    return result
  }
}
