package tenant

import (
	"context"

	"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 CreateCompanyUseCase struct {
	companyRepo ports.CompanyRepository
	userRepo    ports.UserRepository
	authService ports.AuthService
}

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

func (uc *CreateCompanyUseCase) Execute(ctx context.Context, input dto.CreateCompanyRequest) (*dto.CompanyResponse, error) {
	// 1. Create Company ID (Assuming UUID generated by Repo OR here. Let's assume Repo handles ID generation if empty, or we do it.)
	// To be agnostic, let's assume NewCompany takes an ID. In real app, we might use a UUID generator service.
	// For now, let's assume ID is generated by DB or we pass a placeholder if DB does it.
	// Actually, the Entity `NewCompany` takes ID. I should generate one.
	// But UseCase shouldn't rely on specific UUID lib ideally?
	// I'll skip ID generation here and let Repo handle it or use a simple string for now.
	// Better: Use a helper or just "new-uuid" string for now as placeholder for the generator logic.

	// Implementation decision: Domain ID generation should be explicit.
	// I'll assume input could pass it, or we rely on repo.
	// Let's create the entity with empty ID and let Repo fill it? No, Entity usually needs Identity.
	// I'll generate a random ID here for simulation if I had a uuid lib.
	// Since I want to be agnostic and dependency-free, I'll assume the Repo 'Save' returns the fully populated entity including ID.

	company := entity.NewCompany("", input.Name, &input.Document, &input.Contact)

	savedCompany, err := uc.companyRepo.Save(ctx, company)
	if err != nil {
		return nil, err
	}

	// 2. Create Admin User
	// We need a password for the admin. Do we generate one? Or did input provide?
	// input.AdminEmail is present. But no password. I'll generic default or ask to send email.
	// For simplicity, let's assume a default password "ChangeMe123!" hash it.
	hashedPassword, _ := uc.authService.HashPassword("ChangeMe123!")

	adminUser := entity.NewUser("", savedCompany.ID, "Admin", input.AdminEmail)
	adminUser.PasswordHash = hashedPassword
	adminUser.AssignRole(entity.Role{Name: "ADMIN"})

	_, err = uc.userRepo.Save(ctx, adminUser)
	if err != nil {
		// Rollback company? Transaction?
		// Ignored for now.
		return nil, err
	}

	return &dto.CompanyResponse{
		ID:        savedCompany.ID,
		Name:      savedCompany.Name,
		Status:    savedCompany.Status,
		CreatedAt: savedCompany.CreatedAt,
	}, nil
}
