package auth

import (
	"context"
	"database/sql"
	"errors"
)

type User struct {
	ID           string
	Username     string
	PasswordHash string
	Role         string // Legacy field, kept for backward compatibility
	CreatedAt    string
}

type UserStore struct {
	DB *sql.DB
}

func NewUserStore(db *sql.DB) *UserStore {
	return &UserStore{DB: db}
}

// GetUserByUsername retrieves a user by username
func (s *UserStore) GetUserByUsername(ctx context.Context, username string) (*User, error) {
	var user User
	err := s.DB.QueryRowContext(ctx,
		`SELECT id, username, password_hash, role, created_at FROM users WHERE username = ?`,
		username).Scan(&user.ID, &user.Username, &user.PasswordHash, &user.Role, &user.CreatedAt)
	if err != nil {
		if err == sql.ErrNoRows {
			return nil, errors.New("user not found")
		}
		return nil, err
	}
	return &user, nil
}

// GetUserByID retrieves a user by ID
func (s *UserStore) GetUserByID(ctx context.Context, userID string) (*User, error) {
	var user User
	err := s.DB.QueryRowContext(ctx,
		`SELECT id, username, password_hash, role, created_at FROM users WHERE id = ?`,
		userID).Scan(&user.ID, &user.Username, &user.PasswordHash, &user.Role, &user.CreatedAt)
	if err != nil {
		if err == sql.ErrNoRows {
			return nil, errors.New("user not found")
		}
		return nil, err
	}
	return &user, nil
}

// CreateUser creates a new user
func (s *UserStore) CreateUser(ctx context.Context, username, password string) (*User, error) {
	passwordHash, err := HashPassword(password)
	if err != nil {
		return nil, err
	}

	userID := username // Using username as ID for simplicity, could use UUID
	_, err = s.DB.ExecContext(ctx,
		`INSERT INTO users (id, username, password_hash) VALUES (?, ?, ?)`,
		userID, username, passwordHash)
	if err != nil {
		return nil, err
	}

	return s.GetUserByID(ctx, userID)
}

// UpdatePassword updates a user's password
func (s *UserStore) UpdatePassword(ctx context.Context, userID, newPassword string) error {
	passwordHash, err := HashPassword(newPassword)
	if err != nil {
		return err
	}

	_, err = s.DB.ExecContext(ctx,
		`UPDATE users SET password_hash = ? WHERE id = ?`,
		passwordHash, userID)
	return err
}

// Authenticate verifies username and password
func (s *UserStore) Authenticate(ctx context.Context, username, password string) (*User, error) {
	user, err := s.GetUserByUsername(ctx, username)
	if err != nil {
		return nil, err
	}

	valid, err := VerifyPassword(password, user.PasswordHash)
	if err != nil {
		return nil, err
	}
	if !valid {
		return nil, errors.New("invalid password")
	}

	return user, nil
}
