// Copyright Epic Games, Inc. All Rights Reserved.
// UE5 Modular Game Framework — GI_GameFramework Implementation

#include "Core/GI_GameFramework.h"
#include "Core/DA_GameTagRegistry.h"
#include "Logging/LogMacros.h"

DEFINE_LOG_CATEGORY_STATIC(LogFramework, Log, All);

UGI_GameFramework::UGI_GameFramework()
{
	PlatformType = EPlatformType::Generic;
}

// ============================================================================
// Lifecycle
// ============================================================================

void UGI_GameFramework::Init()
{
	Super::Init();

	UE_LOG(LogFramework, Log, TEXT("GI_GameFramework::Init — Framework boot starting..."));

	// Step 1: Platform-specific initialization.
	InitPlatformServices();

	// Step 2: Register services (GameplayTag → Subsystem class mapping).
	RegisterServices();

	// Step 3: Validate the tag registry.
	if (bValidateTagsOnInit)
	{
		ValidateFrameworkTags();
	}

	// Step 4: Check if TagRegistry is valid.
	if (!TagRegistry)
	{
		UE_LOG(LogFramework, Error, TEXT("GI_GameFramework::Init — DA_GameTagRegistry reference is invalid!"));
		OnFrameworkInitFailed.Broadcast(TEXT("DA_GameTagRegistry reference not assigned in GI_GameFramework"));
		return;
	}

	// Step 5: Mark framework as ready.
	bFrameworkInitialized = true;

	// Step 6: Broadcast readiness.
	OnFrameworkReady.Broadcast();
	OnPlatformReady.Broadcast();

	UE_LOG(LogFramework, Log, TEXT("GI_GameFramework::Init — Framework ready. Phase: MainMenu"));
}

void UGI_GameFramework::Shutdown()
{
	UE_LOG(LogFramework, Log, TEXT("GI_GameFramework::Shutdown"));
	Super::Shutdown();
}

// ============================================================================
// Game Phase State Machine
// ============================================================================

void UGI_GameFramework::SetGamePhase(EGamePhase NewPhase)
{
	if (CurrentGamePhase == NewPhase)
	{
		return; // Prevent infinite loops from redundant sets.
	}

	EGamePhase OldPhase = CurrentGamePhase;
	CurrentGamePhase = NewPhase;

	UE_LOG(LogFramework, Log, TEXT("GI_GameFramework::SetGamePhase — %d -> %d"),
		static_cast<int32>(OldPhase), static_cast<int32>(NewPhase));

	OnGamePhaseChanged.Broadcast(NewPhase);
}

// ============================================================================
// Session Flags
// ============================================================================

bool UGI_GameFramework::GetSessionFlag(FGameplayTag FlagTag) const
{
	if (!FlagTag.IsValid())
	{
		return false;
	}

	const bool* Value = SessionFlags.Find(FlagTag);
	return Value ? *Value : false;
}

void UGI_GameFramework::SetSessionFlag(FGameplayTag FlagTag, bool bValue)
{
	if (FlagTag.IsValid())
	{
		SessionFlags.Add(FlagTag, bValue);
	}
}

void UGI_GameFramework::ClearAllSessionFlags()
{
	SessionFlags.Empty();
	UE_LOG(LogFramework, Verbose, TEXT("GI_GameFramework::ClearAllSessionFlags — All session flags cleared"));
}

// ============================================================================
// Save Slot Management
// ============================================================================

void UGI_GameFramework::SetActiveSlot(int32 SlotIndex)
{
	ActiveSlotIndex = SlotIndex;
	UE_LOG(LogFramework, Log, TEXT("GI_GameFramework::SetActiveSlot — Slot %d"), SlotIndex);
}

// ============================================================================
// Service Resolution
// ============================================================================

UGameInstanceSubsystem* UGI_GameFramework::GetService(FGameplayTag ServiceTag) const
{
	if (!ServiceTag.IsValid())
	{
		UE_LOG(LogFramework, Warning, TEXT("GI_GameFramework::GetService — Invalid service tag"));
		return nullptr;
	}

	const TSubclassOf<UGameInstanceSubsystem>* SubsystemClass = ServiceRegistry.Find(ServiceTag);
	if (!SubsystemClass || !*SubsystemClass)
	{
		UE_LOG(LogFramework, Warning, TEXT("GI_GameFramework::GetService — No subsystem mapped for tag '%s'"),
			*ServiceTag.GetTagName().ToString());
		return nullptr;
	}

	UGameInstanceSubsystem* Subsystem = GetSubsystemBase(*SubsystemClass);
	if (!Subsystem)
	{
		UE_LOG(LogFramework, Warning, TEXT("GI_GameFramework::GetService — Subsystem '%s' not available"),
			*(*SubsystemClass)->GetName());
	}

	return Subsystem;
}

// ============================================================================
// Internal Methods
// ============================================================================

void UGI_GameFramework::InitPlatformServices()
{
	// Detect platform from command-line override first.
	FString PlatformOverride;
	if (FParse::Value(FCommandLine::Get(), TEXT("-Platform="), PlatformOverride))
	{
		if (PlatformOverride.Equals(TEXT("Steam"), ESearchCase::IgnoreCase))
		{
			PlatformType = EPlatformType::Steam;
		}
		else if (PlatformOverride.Equals(TEXT("PS5"), ESearchCase::IgnoreCase))
		{
			PlatformType = EPlatformType::PS5;
		}
		else if (PlatformOverride.Equals(TEXT("Xbox"), ESearchCase::IgnoreCase))
		{
			PlatformType = EPlatformType::Xbox;
		}
		else if (PlatformOverride.Equals(TEXT("Switch"), ESearchCase::IgnoreCase))
		{
			PlatformType = EPlatformType::Switch;
		}
	}

	UE_LOG(LogFramework, Log, TEXT("GI_GameFramework::InitPlatformServices — Platform: %d"),
		static_cast<int32>(PlatformType));

	// Platform-specific initialization hooks.
	// Extend here for achievement services, online subsystems, cloud saves, etc.
	switch (PlatformType)
	{
	case EPlatformType::Steam:
		// TODO: Init Steam OSS, achievements, cloud saves
		break;
	case EPlatformType::PS5:
		// TODO: Init PSN services
		break;
	case EPlatformType::Xbox:
		// TODO: Init Xbox Live services
		break;
	case EPlatformType::Switch:
		// TODO: Init Nintendo services
		break;
	default:
		break;
	}
}

void UGI_GameFramework::ValidateFrameworkTags()
{
	if (!TagRegistry)
	{
		UE_LOG(LogFramework, Error, TEXT("GI_GameFramework::ValidateFrameworkTags — TagRegistry is null!"));
		return;
	}

	TArray<FGameplayTag> AllTags = TagRegistry->GetAllRegisteredTags();

	if (AllTags.Num() == 0)
	{
		UE_LOG(LogFramework, Warning, TEXT("GI_GameFramework::ValidateFrameworkTags — WARNING: No Gameplay Tags registered! "
			"Check Project Settings → GameplayTags → Gameplay Tag Table List. "
			"All 11 Data Tables must be added."));
	}
	else
	{
		UE_LOG(LogFramework, Log, TEXT("GI_GameFramework::ValidateFrameworkTags — %d tags registered across 11 Data Tables"),
			AllTags.Num());
	}

	if (bLogTagsOnInit)
	{
		TagRegistry->LogAllTags();
	}
}

void UGI_GameFramework::RegisterServices()
{
	// Maps GameplayTag identifiers to subsystem classes.
	// This is the canonical service registry — extend here for new subsystems.
	// Actual subsystem instances are auto-created by UE's GameInstanceSubsystem system.

	// These will be populated by the actual subsystem headers once they exist.
	// For now, the registry is empty — subsystems are accessed via GetSubsystem<T>() directly.
	UE_LOG(LogFramework, Verbose, TEXT("GI_GameFramework::RegisterServices — Service registry initialized"));
}
