package repository import ( "database/sql" "time" "aggios-app/backend/internal/domain" "github.com/google/uuid" ) // UserRepository handles database operations for users type UserRepository struct { db *sql.DB } // NewUserRepository creates a new user repository func NewUserRepository(db *sql.DB) *UserRepository { return &UserRepository{db: db} } // Create creates a new user func (r *UserRepository) Create(user *domain.User) error { query := ` INSERT INTO users (id, tenant_id, email, password_hash, first_name, role, is_active, created_at, updated_at) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9) RETURNING id, created_at, updated_at ` now := time.Now() user.ID = uuid.New() user.CreatedAt = now user.UpdatedAt = now // Default role to CLIENTE if not specified if user.Role == "" { user.Role = "CLIENTE" } return r.db.QueryRow( query, user.ID, user.TenantID, user.Email, user.Password, user.Name, user.Role, true, // is_active user.CreatedAt, user.UpdatedAt, ).Scan(&user.ID, &user.CreatedAt, &user.UpdatedAt) } // FindByEmail finds a user by email func (r *UserRepository) FindByEmail(email string) (*domain.User, error) { query := ` SELECT id, tenant_id, email, password_hash, first_name, role, created_at, updated_at FROM users WHERE email = $1 AND is_active = true ` user := &domain.User{} err := r.db.QueryRow(query, email).Scan( &user.ID, &user.TenantID, &user.Email, &user.Password, &user.Name, &user.Role, &user.CreatedAt, &user.UpdatedAt, ) if err == sql.ErrNoRows { return nil, nil } return user, err } // FindByID finds a user by ID func (r *UserRepository) FindByID(id uuid.UUID) (*domain.User, error) { query := ` SELECT id, tenant_id, email, password_hash, first_name, role, created_at, updated_at FROM users WHERE id = $1 AND is_active = true ` user := &domain.User{} err := r.db.QueryRow(query, id).Scan( &user.ID, &user.TenantID, &user.Email, &user.Password, &user.Name, &user.Role, &user.CreatedAt, &user.UpdatedAt, ) if err == sql.ErrNoRows { return nil, nil } return user, err } // EmailExists checks if an email is already registered func (r *UserRepository) EmailExists(email string) (bool, error) { var exists bool query := `SELECT EXISTS(SELECT 1 FROM users WHERE email = $1)` err := r.db.QueryRow(query, email).Scan(&exists) return exists, err } // UpdatePassword updates a user's password func (r *UserRepository) UpdatePassword(userID, hashedPassword string) error { query := `UPDATE users SET password_hash = $1, updated_at = $2 WHERE id = $3` _, err := r.db.Exec(query, hashedPassword, time.Now(), userID) return err } // FindAdminByTenantID returns the primary admin user for a tenant func (r *UserRepository) FindAdminByTenantID(tenantID uuid.UUID) (*domain.User, error) { query := ` SELECT id, tenant_id, email, password_hash, first_name, role, created_at, updated_at FROM users WHERE tenant_id = $1 AND role = 'ADMIN_AGENCIA' AND is_active = true ORDER BY created_at ASC LIMIT 1 ` user := &domain.User{} err := r.db.QueryRow(query, tenantID).Scan( &user.ID, &user.TenantID, &user.Email, &user.Password, &user.Name, &user.Role, &user.CreatedAt, &user.UpdatedAt, ) if err == sql.ErrNoRows { return nil, nil } if err != nil { return nil, err } return user, nil }