import { BaseModel, beforeCreate, column, hasOne, manyToMany } from '@adonisjs/lucid/orm'
import type { HasOne, ManyToMany } from '@adonisjs/lucid/types/relations'
import hash from '@adonisjs/core/services/hash'
import { compose } from '@adonisjs/core/helpers'
import { withAuthFinder } from '@adonisjs/auth/mixins/lucid'
import { DateTime } from 'luxon'
import { v7 as uuidv7 } from 'uuid'
import UserPref from '#models/user_pref'
import Role from '#models/role'

const AuthFinder = withAuthFinder(() => hash.use(), {
  uids: ['email'],
  passwordColumnName: 'password',
})

export default class User extends compose(BaseModel, AuthFinder) {
  static incrementing = false

  @column({ isPrimary: true })
  declare id: string

  @column()
  declare email: string

  @column({ serializeAs: null })
  declare password: string

  @column()
  declare username: string | null

  @column({ serializeAs: null })
  declare legacyPassword: string | null

  @column()
  declare status: 'active' | 'banned' | 'pending'

  @column.date()
  declare dateOfBirth: DateTime

  @column()
  declare sex: 'male' | 'female' | 'other'

  @column.dateTime()
  declare agreedToTos: DateTime

  @column.dateTime()
  declare passwordChangedAt: DateTime | null

  @column.dateTime({ autoCreate: true })
  declare createdAt: DateTime

  @column.dateTime({ autoCreate: true, autoUpdate: true })
  declare updatedAt: DateTime | null

  @column.dateTime()
  declare deletedAt: DateTime | null

  @hasOne(() => UserPref)
  declare userPref: HasOne<typeof UserPref>

  @manyToMany(() => Role, {
    pivotTable: 'user_roles',
    pivotForeignKey: 'user_id',
    pivotRelatedForeignKey: 'role_id',
    pivotColumns: ['assigned_at', 'assigned_by'],
  })
  declare roles: ManyToMany<typeof Role>

  async softDelete() {
    this.deletedAt = DateTime.now()
    await this.save()
  }

  @beforeCreate()
  static assignId(user: User) {
    if (!user.id) {
      user.id = uuidv7()
    }
  }

  get initials() {
    return (this.username ?? '').slice(0, 2).toUpperCase()
  }
}
