package repository

import (
	"database/sql"
	"log"
	"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) {
	log.Printf("🔍 FindByEmail called with: %s", email)
	
	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 {
		log.Printf("❌ User not found: %s", email)
		return nil, nil
	}
	if err != nil {
		log.Printf("❌ DB error finding user %s: %v", email, err)
		return nil, err
	}

	log.Printf("✅ Found user: %s, role: %s", user.Email, user.Role)
	return user, nil
}

// 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
}
// ListByTenantID returns all users for a tenant (excluding the tenant admin)
func (r *UserRepository) ListByTenantID(tenantID uuid.UUID) ([]domain.User, error) {
	query := `
		SELECT id, tenant_id, email, password_hash, first_name, role, created_at, updated_at, 
		       agency_role, created_by, collaborator_created_at
		FROM users
		WHERE tenant_id = $1 AND is_active = true AND role != 'SUPERADMIN'
		ORDER BY created_at DESC
	`

	rows, err := r.db.Query(query, tenantID)
	if err != nil {
		return nil, err
	}
	defer rows.Close()

	var users []domain.User
	for rows.Next() {
		user := domain.User{}
		err := rows.Scan(
			&user.ID,
			&user.TenantID,
			&user.Email,
			&user.Password,
			&user.Name,
			&user.Role,
			&user.CreatedAt,
			&user.UpdatedAt,
			&user.AgencyRole,
			&user.CreatedBy,
			&user.CollaboratorCreatedAt,
		)
		if err != nil {
			return nil, err
		}
		users = append(users, user)
	}

	return users, rows.Err()
}

// GetByID returns a user by ID
func (r *UserRepository) GetByID(id uuid.UUID) (*domain.User, error) {
	return r.FindByID(id)
}

// Delete marks a user as inactive
func (r *UserRepository) Delete(id uuid.UUID) error {
	query := `
		UPDATE users
		SET is_active = false, updated_at = NOW()
		WHERE id = $1
	`

	result, err := r.db.Exec(query, id)
	if err != nil {
		return err
	}

	rows, err := result.RowsAffected()
	if err != nil {
		return err
	}

	if rows == 0 {
		return sql.ErrNoRows
	}

	return nil
}