package auth

import (
	"context"
	"errors"
	"fmt"
	"strings"

	"github.com/rede5/gohorsejobs/backend/internal/core/domain/entity"
	"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
	fmt.Printf("[LOGIN DEBUG] Searching for user: %s\n", input.Email)
	user, err := uc.userRepo.FindByEmail(ctx, input.Email)
	if err != nil {
		fmt.Printf("[LOGIN DEBUG] Error finding user: %v\n", err)
		return nil, errors.New("invalid credentials")
	}

	// Check if user was found
	if user == nil {
		fmt.Printf("[LOGIN DEBUG] User not found (nil)\n")
		return nil, errors.New("invalid credentials")
	}

	fmt.Printf("[LOGIN DEBUG] User found: ID=%s, Status=%s, HashPrefix=%s\n", user.ID, user.Status, user.PasswordHash[:10])

	// 2. Verify Password
	if !uc.authService.VerifyPassword(user.PasswordHash, input.Password) {
		fmt.Printf("[LOGIN DEBUG] Password verification FAILED\n")
		return nil, errors.New("invalid credentials")
	}
	fmt.Printf("[LOGIN DEBUG] Password verification PASSED\n")

	// 3. Check Status
	isActive := strings.EqualFold(user.Status, entity.UserStatusActive)
	isForceChange := strings.EqualFold(user.Status, entity.UserStatusForceChangePassword)

	if !isActive && !isForceChange {
		fmt.Printf("[LOGIN DEBUG] Status check FAILED: Expected %s or %s, got '%s'\n",
			entity.UserStatusActive, entity.UserStatusForceChangePassword, user.Status)
		return nil, errors.New("account inactive")
	}
	fmt.Printf("[LOGIN DEBUG] Status check PASSED (Active: %v, ForceChange: %v)\n", isActive, isForceChange)

	// 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 {
		fmt.Printf("[LOGIN DEBUG] Token generation FAILED: %v\n", err)
		return nil, errors.New("failed to generate token")
	}

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