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

#include "Core/GM_CoreGameMode.h"
#include "Core/GI_GameFramework.h"
#include "Core/GS_CoreGameState.h"
#include "GameFramework/PlayerController.h"
#include "GameFramework/PlayerState.h"
#include "Engine/World.h"
#include "Kismet/GameplayStatics.h"

DEFINE_LOG_CATEGORY_STATIC(LogFrameworkGameMode, Log, All);

AGM_CoreGameMode::AGM_CoreGameMode()
{
	// Set defaults — can be overridden in Blueprint subclasses or config.
	// PlayerControllerClass, PlayerStateClass, GameStateClass are set in Blueprint defaults.
}

// ============================================================================
// Overrides
// ============================================================================

void AGM_CoreGameMode::InitGame(const FString& MapName, const FString& Options, FString& ErrorMessage)
{
	Super::InitGame(MapName, Options, ErrorMessage);

	// Cache the framework GameInstance.
	CachedFramework = Cast<UGI_GameFramework>(GetGameInstance());
	if (!CachedFramework)
	{
		UE_LOG(LogFrameworkGameMode, Warning, TEXT("GM_CoreGameMode::InitGame — GI_GameFramework not found as GameInstance"));
	}

	UE_LOG(LogFrameworkGameMode, Log, TEXT("GM_CoreGameMode::InitGame — Map: %s"), *MapName);
}

void AGM_CoreGameMode::BeginPlay()
{
	Super::BeginPlay();

	// Set initial game phase if coming from MainMenu.
	if (CachedFramework && CachedFramework->CurrentGamePhase == EGamePhase::MainMenu)
	{
		CachedFramework->SetGamePhase(EGamePhase::InGame);
	}

	UE_LOG(LogFrameworkGameMode, Log, TEXT("GM_CoreGameMode::BeginPlay"));
}

// ============================================================================
// Chapter Management
// ============================================================================

void AGM_CoreGameMode::TransitionToChapter(FGameplayTag ChapterTag)
{
	if (!ChapterTag.IsValid())
	{
		UE_LOG(LogFrameworkGameMode, Warning, TEXT("GM_CoreGameMode::TransitionToChapter — Invalid chapter tag"));
		return;
	}

	// Prevent transitions during loading.
	if (CachedFramework && CachedFramework->CurrentGamePhase == EGamePhase::Loading)
	{
		UE_LOG(LogFrameworkGameMode, Warning, TEXT("GM_CoreGameMode::TransitionToChapter — Already loading, ignoring transition to '%s'"),
			*ChapterTag.GetTagName().ToString());
		return;
	}

	UE_LOG(LogFrameworkGameMode, Log, TEXT("GM_CoreGameMode::TransitionToChapter — '%s'"), *ChapterTag.GetTagName().ToString());

	CurrentChapterTag = ChapterTag;

	if (HasAuthority())
	{
		ServerTransitionToChapter(ChapterTag);
	}
}

void AGM_CoreGameMode::ServerTransitionToChapter(FGameplayTag ChapterTag)
{
	if (!CachedFramework)
	{
		return;
	}

	// Set phase to Loading.
	CachedFramework->SetGamePhase(EGamePhase::Loading);

	// Sync chapter to GameState.
	AGS_CoreGameState* GS = GetGameState<AGS_CoreGameState>();
	if (GS)
	{
		GS->SetChapter(ChapterTag);
	}

	// TODO: Open/stream the level associated with ChapterTag.
	// UGameplayStatics::OpenLevel(this, ChapterLevelName);

	// Broadcast transition.
	OnChapterTransition.Broadcast(ChapterTag);

	// On level loaded, OnChapterLevelLoaded() would be called to restore InGame phase.
}

void AGM_CoreGameMode::OnChapterLevelLoaded(FGameplayTag ChapterTag)
{
	if (CachedFramework)
	{
		CachedFramework->SetGamePhase(EGamePhase::InGame);
	}

	UE_LOG(LogFrameworkGameMode, Log, TEXT("GM_CoreGameMode::OnChapterLevelLoaded — '%s'"), *ChapterTag.GetTagName().ToString());
}

// ============================================================================
// Death Handling
// ============================================================================

void AGM_CoreGameMode::HandlePlayerDead(AController* DeadController)
{
	if (!DeadController)
	{
		UE_LOG(LogFrameworkGameMode, Warning, TEXT("GM_CoreGameMode::HandlePlayerDead — Invalid controller"));
		return;
	}

	UE_LOG(LogFrameworkGameMode, Log, TEXT("GM_CoreGameMode::HandlePlayerDead — %s"), *DeadController->GetName());

	// Disable pause during death sequence.
	bPauseAllowed = false;

	if (CachedFramework)
	{
		CachedFramework->SetGamePhase(EGamePhase::DeathLoop);
	}

	// TODO: Decision logic — AltDeathSpace vs checkpoint respawn.
	// For now, route to checkpoint respawn through the save system.
	UE_LOG(LogFrameworkGameMode, Log, TEXT("GM_CoreGameMode::HandlePlayerDead — Routing to respawn..."));
}

// ============================================================================
// Ending / Game Over
// ============================================================================

void AGM_CoreGameMode::TriggerEnding(FGameplayTag EndingTag)
{
	if (!EndingTag.IsValid())
	{
		UE_LOG(LogFrameworkGameMode, Warning, TEXT("GM_CoreGameMode::TriggerEnding — Invalid ending tag"));
		return;
	}

	UE_LOG(LogFrameworkGameMode, Log, TEXT("GM_CoreGameMode::TriggerEnding — '%s'"), *EndingTag.GetTagName().ToString());

	OnGameOverTriggered.Broadcast(EndingTag);

	// TODO: Pass to BPC_EndingAccumulator for accumulation + ending determination.
}
