import {
  Entity,
  PrimaryGeneratedColumn,
  Column,
  ManyToOne,
  JoinColumn,
  OneToMany,
  BeforeInsert,
  AfterLoad,
} from "typeorm"
import * as bcrypt from "bcrypt"
import * as process from "node:process"
import { isEmpty } from "../../../utils/helpers"
import { Role } from "../../role/entities/role.entity"
import { UserLogin } from "./user-login.entity"
import { Company } from "../../company/entities/company.entity"
import { Employee } from "../../employees/entities/employee.entity"
import { BaseEntity } from "../../common/entities/base.entity"

@Entity("users")
export class Auth extends BaseEntity {
  @PrimaryGeneratedColumn()
  id: number

  @Column({ type: "int", nullable: true })
  company_id: number

  @Column({ type: "int", nullable: true })
  employee_id: number

  @Column({ type: "varchar", length: 150, nullable: false })
  first_name: string

  @Column({ type: "varchar", length: 150, nullable: false })
  last_name: string

  @Column({ type: "varchar", length: 150, nullable: false })
  email: string

  @Column({ type: "varchar", length: 255, nullable: true })
  password: string

  @Column({ type: "varchar", length: 20, nullable: true })
  phone: string

  @Column({ type: "varchar", length: 255, nullable: true })
  profile_image: string

  @Column({ type: "int", nullable: false })
  role_id: number

  @Column({ type: "smallint", default: 1 })
  status: number

  @Column({ type: "timestamp", nullable: true })
  last_login_at: Date

  @Column({ type: "varchar", length: 100, nullable: true })
  slug: string

  @Column({ type: "boolean", default: true })
  is_email_verified: boolean

  @Column({ type: "varchar", length: 500, nullable: true })
  email_verification_token: string

  // ====== RELATIONS ======

  @ManyToOne(() => Company)
  @JoinColumn({ name: "company_id" })
  company: Company

  @ManyToOne(() => Employee)
  @JoinColumn({ name: "employee_id" })
  employee: Employee

  @ManyToOne(() => Role, (role) => role.users)
  @JoinColumn({ name: "role_id" })
  role: Role

  @OneToMany(() => UserLogin, (userLogins) => userLogins.user)
  userLogins: UserLogin[]

  // ====== PASSWORD HASHING ======
  @BeforeInsert()
  async hashPassword(password: string) {
    if (!isEmpty(this.password)) {
      const salt = await bcrypt.genSalt()
      this.password = await bcrypt.hash(password || this.password, salt)
    }
  }

  // ====== PROFILE IMAGE FALLBACK ======
  @AfterLoad()
  async setProfileImageUrl() {
    if (isEmpty(this.profile_image)) {
      this.profile_image = `${process.env.BASE_URL}static-images/png/img-plceholder@2x.png`
    } else {
      this.profile_image = process.env.BASE_URL + this.profile_image
    }
  }

  // extra (not saved to DB)
  access_token?: string
}
