#include "ZeusJobsSubsystem.h"

#include "AssetRegistry/AssetRegistryModule.h"
#include "Modules/ModuleManager.h"
#include "ZeusJobDataAsset.h"

DEFINE_LOG_CATEGORY_STATIC(LogZeusJobs, Log, All);

void UZeusJobsSubsystem::Initialize(FSubsystemCollectionBase& Collection)
{
	Super::Initialize(Collection);
	LoadJobsFromAssetRegistry();
	UE_LOG(LogZeusJobs, Log, TEXT("[ZeusJobsSubsystem] Initialize: %d job(s) carregados"), CachedJobs.Num());
}

void UZeusJobsSubsystem::Deinitialize()
{
	CachedJobs.Empty();
	Super::Deinitialize();
}

void UZeusJobsSubsystem::LoadJobsFromAssetRegistry()
{
	FAssetRegistryModule& AssetRegistryModule =
		FModuleManager::LoadModuleChecked<FAssetRegistryModule>("AssetRegistry");
	IAssetRegistry& AR = AssetRegistryModule.Get();

	// Editor pode chamar antes de scan inicial. Standalone/PIE scan ja' rodou.
	// SearchAllAssets(false) = nao-blocking; assume cache populado em runtime.
#if WITH_EDITOR
	AR.SearchAllAssets(true);  // bloqueia editor; ok em Initialize
#endif

	TArray<FAssetData> Assets;
	const FTopLevelAssetPath ClassPath(UZeusJobDataAsset::StaticClass()->GetClassPathName());
	AR.GetAssetsByClass(ClassPath, Assets, /*bSearchSubClasses*/ true);

	for (const FAssetData& AssetData : Assets)
	{
		UZeusJobDataAsset* Job = Cast<UZeusJobDataAsset>(AssetData.GetAsset());
		if (Job == nullptr) { continue; }

		if (CachedJobs.Contains(Job->ClassId))
		{
			UE_LOG(LogZeusJobs, Warning,
				TEXT("[ZeusJobsSubsystem] Duplicate ClassId=%d (existing=%s, new=%s) — ignorando segundo"),
				Job->ClassId,
				*CachedJobs[Job->ClassId]->GetName(),
				*Job->GetName());
			continue;
		}

		CachedJobs.Add(Job->ClassId, Job);
		UE_LOG(LogZeusJobs, Verbose,
			TEXT("[ZeusJobsSubsystem] Cached classId=%d name=%s display=%s"),
			Job->ClassId, *Job->TechnicalName, *Job->DisplayName.ToString());
	}
}

UZeusJobDataAsset* UZeusJobsSubsystem::GetJobData(int32 ClassId) const
{
	if (const TObjectPtr<UZeusJobDataAsset>* Found = CachedJobs.Find(ClassId))
	{
		return Found->Get();
	}
	return nullptr;
}

TArray<UZeusJobDataAsset*> UZeusJobsSubsystem::GetJobsByTier(EZeusJobTier Tier) const
{
	TArray<UZeusJobDataAsset*> Out;
	Out.Reserve(CachedJobs.Num());
	for (const TPair<int32, TObjectPtr<UZeusJobDataAsset>>& Pair : CachedJobs)
	{
		if (Pair.Value && Pair.Value->Tier == Tier)
		{
			Out.Add(Pair.Value.Get());
		}
	}
	return Out;
}

TArray<UZeusJobDataAsset*> UZeusJobsSubsystem::GetEligibleNextJobs(int32 CurrentClassId) const
{
	TArray<UZeusJobDataAsset*> Out;
	Out.Reserve(4);  // tipico: 2-6 destinos
	for (const TPair<int32, TObjectPtr<UZeusJobDataAsset>>& Pair : CachedJobs)
	{
		if (Pair.Value && Pair.Value->ParentClassId == CurrentClassId
		    && Pair.Value->ClassId != CurrentClassId)
		{
			Out.Add(Pair.Value.Get());
		}
	}
	return Out;
}
