import { nanoid } from 'nanoid'
import { File, type IFile } from '../models/store/File.js'
import { Thing } from '../models/Thing.js'
import type { DataDomain, DataDomainSchema } from './DataDomain.js'
import { DomainFileKind } from '../models/kinds.js'

export interface IDomainFile extends IFile {
  kind: typeof DomainFileKind
}

/**
 * Used by the store. A file definition for the DataDomain
 */
export class DomainFile extends File {
  override kind = DomainFileKind

  static override fromName(name: string, organization: string, owner?: string): DomainFile {
    return super.fromName(name, organization, owner, DomainFileKind) as DomainFile
  }

  /**
   * Creates the file definition for a DataNamespace contents.
   *
   * @param input The data namespace instance or schema.
   * @param owner Optional owner to set.
   */
  static fromDataDomain(input: DataDomain | DataDomainSchema, organization: string, owner?: string): DomainFile {
    let final: DataDomainSchema
    if (typeof (input as DataDomain).toJSON === 'function') {
      final = (input as DataDomain).toJSON()
    } else {
      final = input as DataDomainSchema
    }
    const init: IDomainFile = {
      kind: DomainFileKind,
      key: final.key,
      organization,
      info: { ...final.info },
      lastModified: { user: owner || '', time: 0, byMe: false },
      owner,
      parents: [],
      permissionIds: [],
      permissions: [],
    }
    return new DomainFile(init)
  }

  constructor(input?: string | IDomainFile) {
    super()
    let init: IDomainFile
    if (typeof input === 'string') {
      init = JSON.parse(input)
    } else if (typeof input === 'object') {
      init = input
    } else {
      init = {
        kind: DomainFileKind,
        key: nanoid(),
        organization: '',
        info: Thing.fromName('').toJSON(),
        parents: [],
        permissionIds: [],
        permissions: [],
        lastModified: { user: '', time: 0, byMe: false },
      }
    }
    this.new(init)
  }

  override new(init: IDomainFile): this {
    if (!DomainFile.isDomainFile(init)) {
      throw new Error(`Not a data file.`)
    }
    super.new(init)
    this.kind = DomainFileKind
    return this
  }

  static isDomainFile(input: unknown): boolean {
    const typed = input as IDomainFile
    if (!input || typed.kind !== DomainFileKind) {
      return false
    }
    return true
  }

  override toJSON(): IDomainFile {
    const result: IDomainFile = {
      ...super.toJSON(),
      kind: DomainFileKind,
    }
    return result
  }
}
