import {
  BeforeInsert,
  Column,
  CreateDateColumn,
  Entity,
  JoinColumn,
  ManyToOne,
  OneToMany,
  OneToOne,
  PrimaryGeneratedColumn,
  UpdateDateColumn,
} from 'typeorm';
import * as bcrypt from 'bcrypt';
import { Tenant } from '../tenant/tenant.entity';
import { TenantMember } from '../tenant/tenant-member.entity';
import { ApiKey } from '../auth/entities/api-key.entity';

import { UserRole } from './user-role.enum';
import { UserSetting } from './user-setting.entity';

@Entity('users')
export class User {
  @PrimaryGeneratedColumn('uuid')
  id: string;

  @Column({ type: 'text', unique: true })
  username: string;

  @Column({ type: 'text' })
  password: string;

  // Legacy field - kept for backward compatibility, use `role` for new logic
  @Column({ type: 'boolean', default: false })
  isAdmin: boolean;

  @Column({ type: 'text', nullable: false })
  displayName: string;


  // Multi-tenancy: A user can belong to multiple tenants via TenantMember
  @OneToMany(() => TenantMember, (member) => member.user)
  tenantMembers: TenantMember[];

  // Legacy field - kept for backward compatibility if needed, but primary tenant is now determined by context
  @Column({ type: 'text', nullable: true, name: 'tenant_id' })
  tenantId: string;

  // API Keys for external API access
  @OneToMany(() => ApiKey, (apiKey) => apiKey.user)
  apiKeys: ApiKey[];

  // Quota management field
  @Column({ type: 'decimal', precision: 10, scale: 2, default: 0 })
  monthlyCost: number;

  @Column({ type: 'decimal', precision: 10, scale: 2, default: 100 })
  maxCost: number;

  @Column({ type: 'datetime', nullable: true })
  lastQuotaReset: Date;

  @CreateDateColumn({ name: 'created_at' })
  createdAt: Date;

  @UpdateDateColumn({ name: 'updated_at' })
  updatedAt: Date;

  @OneToOne(() => UserSetting, (setting) => setting.user)
  userSetting: UserSetting;

  @BeforeInsert()
  async hashPassword() {
    this.password = await bcrypt.hash(this.password, 10);
  }

  async validatePassword(password: string): Promise<boolean> {
    return bcrypt.compare(password, this.password);
  }
}
