import { Field, ID, ObjectType } from 'type-graphql'
import { Column, Entity, Index, ManyToOne, ManyToMany, PrimaryGeneratedColumn, RelationId } from 'typeorm'

import {
  HistoryActionColumn,
  HistoryActionType,
  HistoryEntityInterface,
  HistoryOriginalIdColumn
} from '@operato/typeorm-history'
import { User } from '@things-factory/auth-base'
import { Domain } from '@things-factory/shell'
import { config } from '@things-factory/env'

import { Process } from './process'
import { ProcessGroup } from '../process-group/process-group'

const ORMCONFIG = config.get('ormconfig', {})
const DATABASE_TYPE = ORMCONFIG.type

@Entity()
@Index(
  'ix_process_history_0',
  (processHistory: ProcessHistory) => [processHistory.originalId, processHistory.version],
  {
    unique: true
  }
)
@ObjectType({ description: 'History Entity of Process' })
export class ProcessHistory implements HistoryEntityInterface<Process> {
  @PrimaryGeneratedColumn('uuid')
  @Field(type => ID)
  readonly id: string

  @Column({ nullable: true, default: 1 })
  @Field({ nullable: true })
  version?: number = 1

  @ManyToOne(type => Domain)
  @Field(type => Domain, { nullable: true })
  domain?: Domain

  @RelationId((process: Process) => process.domain)
  domainId?: string

  @Column()
  @Field()
  name?: string

  @Column({ nullable: true })
  @Field({ nullable: true })
  description?: string

  @Column({
    nullable: true,
    type:
      DATABASE_TYPE == 'mysql' || DATABASE_TYPE == 'mariadb'
        ? 'longtext'
        : DATABASE_TYPE == 'oracle'
        ? 'clob'
        : 'varchar'
  })
  @Field({ nullable: true })
  model?: string

  @Column({
    nullable: true,
    type:
      DATABASE_TYPE == 'mysql' || DATABASE_TYPE == 'mariadb'
        ? 'longtext'
        : DATABASE_TYPE == 'oracle'
        ? 'clob'
        : 'varchar'
  })
  @Field({ nullable: true })
  thumbnail?: string

  @ManyToOne(type => ProcessGroup, group => group.processes)
  @Field(type => ProcessGroup, { nullable: true })
  group?: ProcessGroup

  @RelationId((process: Process) => process.group)
  groupId?: string

  @Column({ nullable: true })
  @Field({ nullable: true })
  createdAt?: Date

  @Column({ nullable: true })
  @Field({ nullable: true })
  updatedAt?: Date

  @ManyToOne(type => User, { nullable: true })
  @Field(type => User, { nullable: true })
  creator?: User

  @RelationId((process: Process) => process.creator)
  creatorId?: string

  @ManyToOne(type => User, { nullable: true })
  @Field(type => User, { nullable: true })
  updater?: User

  @RelationId((process: Process) => process.updater)
  updaterId?: string

  @Column({ nullable: true })
  @Field({ nullable: true })
  deletedAt?: Date

  @HistoryOriginalIdColumn()
  public originalId!: string

  @HistoryActionColumn({
    nullable: false,
    type:
      DATABASE_TYPE == 'postgres' || DATABASE_TYPE == 'mysql' || DATABASE_TYPE == 'mariadb'
        ? 'enum'
        : DATABASE_TYPE == 'oracle'
        ? 'varchar2'
        : 'smallint',
    enum: HistoryActionType
  })
  public action!: HistoryActionType
}
