#pragma once

#include "CoreMinimal.h"
#include "GameFramework/GameModeBase.h"
#include "GameFramework/HUD.h"
#include "GameFramework/Pawn.h"
#include "HyperTwistTraining/HyperTwistCoachDashboardPlayerController.h"
#include "HyperTwistHigherDimensionalTrainingGameMode.generated.h"

class AHyperTwistHigherDimensionalTrainingShellActor;
class ADirectionalLight;
class UCameraComponent;
class UHyperTwistHigherDimensionalHUDWidget;
class USceneComponent;
class USpringArmComponent;

UCLASS(BlueprintType, Blueprintable)
class UNREALHYPERTWIST_API AHyperTwistHigherDimensionalOrbitPawn : public APawn
{
	GENERATED_BODY()

public:
	AHyperTwistHigherDimensionalOrbitPawn();

	virtual void BeginPlay() override;
	virtual void Tick(float DeltaSeconds) override;

	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "HyperTwist|Training|HigherDimensional|Camera")
	TObjectPtr<USceneComponent> SceneRoot = nullptr;

	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "HyperTwist|Training|HigherDimensional|Camera")
	TObjectPtr<USpringArmComponent> SpringArm = nullptr;

	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "HyperTwist|Training|HigherDimensional|Camera")
	TObjectPtr<UCameraComponent> CameraComponent = nullptr;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist|Training|HigherDimensional|Camera")
	float InitialArmLength = 820.0f;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist|Training|HigherDimensional|Camera")
	float MinimumArmLength = 360.0f;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist|Training|HigherDimensional|Camera")
	float MaximumArmLength = 1550.0f;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist|Training|HigherDimensional|Camera")
	float InitialYawDegrees = -34.0f;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist|Training|HigherDimensional|Camera")
	float InitialPitchDegrees = -16.0f;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist|Training|HigherDimensional|Camera")
	float OrbitDegreesPerPixel = 0.24f;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist|Training|HigherDimensional|Camera")
	float ZoomStep = 85.0f;

	UFUNCTION(BlueprintCallable, Category = "HyperTwist|Training|HigherDimensional|Camera")
	void ResetOrbit();

private:
	FVector OrbitFocusPoint = FVector(0.0f, 0.0f, 90.0f);
	float CurrentYawDegrees = -34.0f;
	float CurrentPitchDegrees = -16.0f;

	void RefreshOrbitFocusPoint();
	void ApplyOrbitTransform();
	bool ShouldOrbitFromMouseInput() const;
};

UCLASS(BlueprintType, Blueprintable)
class UNREALHYPERTWIST_API AHyperTwistHigherDimensionalTrainingHUD : public AHUD
{
	GENERATED_BODY()

public:
	virtual void DrawHUD() override;

private:
	TWeakObjectPtr<AHyperTwistHigherDimensionalTrainingShellActor> CachedTrainingShell;

	AHyperTwistHigherDimensionalTrainingShellActor* ResolveTrainingShell();
	void DrawStatusLine(const FString& Text, float X, float& InOutY, const FLinearColor& Color, float Scale = 1.0f);
};

UCLASS(BlueprintType, Blueprintable)
class UNREALHYPERTWIST_API AHyperTwistHigherDimensionalTrainingPlayerController
	: public AHyperTwistCoachDashboardPlayerController
{
	GENERATED_BODY()

public:
	AHyperTwistHigherDimensionalTrainingPlayerController();

	virtual void BeginPlay() override;
	virtual void PlayerTick(float DeltaTime) override;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist|Training|HigherDimensional|HUD")
	TSubclassOf<UHyperTwistHigherDimensionalHUDWidget> PuzzleHudWidgetClass;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist|Training|HigherDimensional|HUD")
	bool bShowPuzzleHud = true;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist|Training|HigherDimensional|HUD")
	int32 PuzzleHudZOrder = 120;

	UPROPERTY(Transient, BlueprintReadOnly, Category = "HyperTwist|Training|HigherDimensional|HUD")
	TObjectPtr<UHyperTwistHigherDimensionalHUDWidget> ActivePuzzleHudWidget = nullptr;

	UFUNCTION(BlueprintPure, Category = "HyperTwist|Training|HigherDimensional|HUD")
	bool IsPuzzleHudReady() const;

protected:
	virtual FString GetPauseMenuTitle() const override;
	virtual FString GetPauseMenuSubtitle() const override;

private:
	TWeakObjectPtr<AHyperTwistHigherDimensionalTrainingShellActor> CachedTrainingShell;
	int32 SelectedMagic120CellIndex = 0;
	int32 SelectedMagic120StickerIndex = 1;
	int32 SelectedMagicCube5DFaceAxis = 4;
	int32 SelectedMagicCube5DSliceMask = 1;
	int32 SelectedMagicCube5DPlaneIndex = 0;
	bool bSelectedMagicCube5DPositiveFace = true;

	AHyperTwistHigherDimensionalTrainingShellActor* ResolveTrainingShell();
	void ToggleCoachDashboardSurface();
	void EnsurePuzzleHud();
	void RefreshPuzzleHud();
	FString BuildMoveSelectionSummary() const;
	void ApplySelectedTurn(bool bPositiveDirection);
	bool UsesMagic120CellRuntime() const;

	UFUNCTION()
	void HandlePreviousPrimarySelection();

	UFUNCTION()
	void HandleNextPrimarySelection();

	UFUNCTION()
	void HandlePreviousSecondarySelection();

	UFUNCTION()
	void HandleNextSecondarySelection();

	UFUNCTION()
	void HandlePreviousTertiarySelection();

	UFUNCTION()
	void HandleNextTertiarySelection();

	UFUNCTION()
	void HandleToggleFaceSide();

	UFUNCTION()
	void HandleNegativeTurn();

	UFUNCTION()
	void HandlePositiveTurn();

	UFUNCTION()
	void HandlePreviousProjectionLayer();

	UFUNCTION()
	void HandleNextProjectionLayer();

	UFUNCTION()
	void HandleToggleAutoRotate();

	UFUNCTION()
	void HandleScramble();

	UFUNCTION()
	void HandleReset();

	UFUNCTION()
	void HandleSave();

	UFUNCTION()
	void HandleLoad();

	UFUNCTION()
	void HandleCoach();

	UFUNCTION()
	void HandleMenu();
};

UCLASS(BlueprintType, Blueprintable)
class UNREALHYPERTWIST_API AHyperTwistHigherDimensionalTrainingGameMode : public AGameModeBase
{
	GENERATED_BODY()

public:
	AHyperTwistHigherDimensionalTrainingGameMode();

	virtual void BeginPlay() override;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist|Training|HigherDimensional")
	TSubclassOf<AHyperTwistHigherDimensionalTrainingShellActor> TrainingShellActorClass;

	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "HyperTwist|Training|HigherDimensional")
	TObjectPtr<AHyperTwistHigherDimensionalTrainingShellActor> ActiveTrainingShell = nullptr;

	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "HyperTwist|Training|HigherDimensional|Presentation")
	TObjectPtr<ADirectionalLight> ActivePresentationLight = nullptr;

	UFUNCTION(BlueprintPure, Category = "HyperTwist|Training|HigherDimensional")
	FString ResolveCurrentFamilyKey() const;

private:
	AHyperTwistHigherDimensionalTrainingShellActor* FindExistingTrainingShell() const;
	AHyperTwistHigherDimensionalTrainingShellActor* SpawnTrainingShell(const FString& FamilyKey);
	void EnsureRuntimeLighting(const FString& FamilyKey);
	void RequestRuntimeReadyDiagnosticsCapture();
	void PersistRuntimeReadinessDiagnostics(
		const FString& FamilyKey,
		const AHyperTwistHigherDimensionalTrainingShellActor* TrainingShell
	) const;
};
