package auth

import (
	"context"
	"errors"
	"fmt"

	"github.com/google/uuid"
	"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 RegisterCandidateUseCase struct {
	userRepo    ports.UserRepository
	companyRepo ports.CompanyRepository
	authService ports.AuthService
}

func NewRegisterCandidateUseCase(uRepo ports.UserRepository, cRepo ports.CompanyRepository, auth ports.AuthService) *RegisterCandidateUseCase {
	return &RegisterCandidateUseCase{
		userRepo:    uRepo,
		companyRepo: cRepo,
		authService: auth,
	}
}

func (uc *RegisterCandidateUseCase) Execute(ctx context.Context, input dto.RegisterCandidateRequest) (*dto.AuthResponse, error) {
	// 1. Check if email exists
	exists, _ := uc.userRepo.FindByEmail(ctx, input.Email)
	if exists != nil {
		return nil, errors.New("email already registered")
	}

	// 2. Hash Password
	hashed, err := uc.authService.HashPassword(input.Password)
	if err != nil {
		return nil, err
	}

	// 3. Create Candidate's Personal Tenant/Workspace
	candidateTenantID := uuid.New().String()
	candidateCompany := entity.NewCompany(
		candidateTenantID,
		fmt.Sprintf("Candidate - %s", input.Name),
		nil, // No document for candidates
		nil, // No contact - will use user's contact info
	)

	_, err = uc.companyRepo.Save(ctx, candidateCompany)
	if err != nil {
		return nil, fmt.Errorf("failed to create candidate workspace: %w", err)
	}

	// 4. Create User Entity
	user := entity.NewUser(uuid.New().String(), candidateTenantID, input.Name, input.Email)
	user.PasswordHash = hashed

	// Set Metadata
	user.Metadata = map[string]interface{}{
		"phone":    input.Phone,
		"username": input.Username,
	}

	// Assign Role
	user.AssignRole(entity.Role{Name: "CANDIDATE"})

	saved, err := uc.userRepo.Save(ctx, user)
	if err != nil {
		return nil, err
	}

	roles := make([]string, len(saved.Roles))
	for i, r := range saved.Roles {
		roles[i] = r.Name
	}

	// 4. Generate Token (Auto-login)
	token, err := uc.authService.GenerateToken(saved.ID, saved.TenantID, roles)
	if err != nil {
		return nil, err
	}

	return &dto.AuthResponse{
		Token: token,
		User: dto.UserResponse{
			ID:        saved.ID,
			Name:      saved.Name,
			Email:     saved.Email,
			Roles:     roles,
			Status:    saved.Status,
			CreatedAt: saved.CreatedAt,
		},
	}, nil
}
