package models

import (
	"time"

	"github.com/google/uuid"
	"gorm.io/gorm"
)

// Role représente un rôle dans le système
type Role struct {
	ID          uuid.UUID `gorm:"type:uuid;primaryKey" json:"id" db:"id"`
	Name        string    `gorm:"uniqueIndex:uni_roles_name;not null;size:50" json:"name" db:"name"`
	DisplayName string    `gorm:"not null;size:100" json:"display_name" db:"display_name"`
	Description string    `gorm:"type:text" json:"description" db:"description"`
	IsSystem    bool      `gorm:"default:false" json:"is_system" db:"is_system"`
	IsActive    bool      `gorm:"default:true" json:"is_active" db:"is_active"`
	CreatedAt   time.Time `gorm:"autoCreateTime" json:"created_at" db:"created_at"`
	UpdatedAt   time.Time `gorm:"autoUpdateTime" json:"updated_at" db:"updated_at"`

	// Relations
	Users       []User       `gorm:"many2many:user_roles;" json:"-"`
	Permissions []Permission `gorm:"many2many:role_permissions;" json:"-"`
}

// BeforeCreate hook GORM pour générer UUID si non défini
func (r *Role) BeforeCreate(tx *gorm.DB) error {
	if r.ID == uuid.Nil {
		r.ID = uuid.New()
	}
	return nil
}

// TableName définit le nom de la table pour GORM
func (Role) TableName() string {
	return "roles"
}

// Permission représente une permission dans le système
type Permission struct {
	ID          uuid.UUID `gorm:"type:uuid;primaryKey" json:"id" db:"id"`
	Name        string    `gorm:"uniqueIndex:uni_permissions_name;not null;size:100" json:"name" db:"name"`
	Resource    string    `gorm:"not null;size:50" json:"resource" db:"resource"`
	Action      string    `gorm:"not null;size:50" json:"action" db:"action"`
	Description string    `gorm:"type:text" json:"description" db:"description"`
	CreatedAt   time.Time `gorm:"autoCreateTime" json:"created_at" db:"created_at"`

	// Relations
	Roles []Role `gorm:"many2many:role_permissions;" json:"-"`
}

// BeforeCreate hook GORM pour générer UUID si non défini
func (p *Permission) BeforeCreate(tx *gorm.DB) error {
	if p.ID == uuid.Nil {
		p.ID = uuid.New()
	}
	return nil
}

// TableName définit le nom de la table pour GORM
func (Permission) TableName() string {
	return "permissions"
}

// UserRole représente l'association entre un utilisateur et un rôle
// MIGRATION UUID: UserID et AssignedBy migrés vers UUID
type UserRole struct {
	ID         uuid.UUID  `gorm:"type:uuid;primaryKey" json:"id" db:"id"`
	UserID     uuid.UUID  `gorm:"type:uuid;not null;index;uniqueIndex:idx_user_roles_unique" json:"user_id" db:"user_id"`
	RoleID     uuid.UUID  `gorm:"type:uuid;not null;index;uniqueIndex:idx_user_roles_unique" json:"role_id" db:"role_id"`
	RoleName   string     `gorm:"column:role;not null;size:50;uniqueIndex:uq_user_roles_user_role" json:"role_name" db:"role"`
	AssignedAt time.Time  `gorm:"default:CURRENT_TIMESTAMP" json:"assigned_at" db:"assigned_at"`
	AssignedBy *uuid.UUID `gorm:"type:uuid;index" json:"assigned_by" db:"assigned_by"`
	ExpiresAt  *time.Time `gorm:"nullable" json:"expires_at" db:"expires_at"`
	IsActive   bool       `gorm:"default:true" json:"is_active" db:"is_active"`

	// Relations
	User User `gorm:"foreignKey:UserID;constraint:OnDelete:CASCADE" json:"-"`
	Role Role `gorm:"foreignKey:RoleID;constraint:OnDelete:CASCADE" json:"-"`
}

// BeforeCreate hook GORM pour générer UUID si non défini et remplir RoleName
func (ur *UserRole) BeforeCreate(tx *gorm.DB) error {
	if ur.ID == uuid.Nil {
		ur.ID = uuid.New()
	}
	// Si RoleName n'est pas défini mais RoleID l'est, récupérer le nom du rôle
	if ur.RoleName == "" && ur.RoleID != uuid.Nil {
		var role Role
		if err := tx.First(&role, ur.RoleID).Error; err == nil {
			ur.RoleName = role.Name
		}
	}
	return nil
}

// TableName définit le nom de la table pour GORM
func (UserRole) TableName() string {
	return "user_roles"
}

// RolePermission représente l'association entre un rôle et une permission
type RolePermission struct {
	RoleID       uuid.UUID `gorm:"type:uuid;primaryKey;index;uniqueIndex:idx_role_permissions_unique" json:"role_id" db:"role_id"`
	PermissionID uuid.UUID `gorm:"type:uuid;primaryKey;index;uniqueIndex:idx_role_permissions_unique" json:"permission_id" db:"permission_id"`

	// Relations
	Role       Role       `gorm:"foreignKey:RoleID;constraint:OnDelete:CASCADE" json:"-"`
	Permission Permission `gorm:"foreignKey:PermissionID;constraint:OnDelete:CASCADE" json:"-"`
}

// TableName définit le nom de la table pour GORM
func (RolePermission) TableName() string {
	return "role_permissions"
}
