package auth

import (
	"context"
	"errors"

	"github.com/rede5/gohorsejobs/backend/internal/core/dto"
	"github.com/rede5/gohorsejobs/backend/internal/core/ports"
)

type LoginUseCase struct {
	userRepo    ports.UserRepository
	authService ports.AuthService
}

func NewLoginUseCase(userRepo ports.UserRepository, authService ports.AuthService) *LoginUseCase {
	return &LoginUseCase{
		userRepo:    userRepo,
		authService: authService,
	}
}

func (uc *LoginUseCase) Execute(ctx context.Context, input dto.LoginRequest) (*dto.AuthResponse, error) {
	// 1. Find User by Email (Global or implicit tenant?)
	// Implementation Note: In this architecture, email should be unique enough or we iterate.
	// For simplicity, assuming email is unique system-wide or we find the active one.
	user, err := uc.userRepo.FindByEmail(ctx, input.Email)
	if err != nil {
		return nil, errors.New("invalid credentials") // Avoid leaking existence
	}

	// 2. Verify Password
	if !uc.authService.VerifyPassword(user.PasswordHash, input.Password) {
		return nil, errors.New("invalid credentials")
	}

	// 3. Check Status
	if user.Status != "ACTIVE" {
		return nil, errors.New("account inactive")
	}

	// 4. Generate Token
	roles := make([]string, len(user.Roles))
	for i, r := range user.Roles {
		roles[i] = r.Name
	}

	token, err := uc.authService.GenerateToken(user.ID, user.TenantID, roles)
	if err != nil {
		return nil, errors.New("failed to generate token")
	}

	// 5. Return Response
	return &dto.AuthResponse{
		Token: token,
		User: dto.UserResponse{
			ID:        user.ID,
			Name:      user.Name,
			Email:     user.Email,
			Roles:     roles,
			Status:    user.Status,
			CreatedAt: user.CreatedAt,
		},
	}, nil
}
