#pragma once

#include "CoreMinimal.h"
#include "Blueprint/UserWidget.h"
#include "HyperTwistTraining/HyperTwistFirstRunLaunchLibrary.h"

#include "HyperTwistFirstRunLaunchWidget.generated.h"

class FJsonObject;
class IHttpRequest;
class UButton;
class UEditableTextBox;
class UHyperTwistSettingsPanelWidget;
class UHyperTwistTrainingSubsystem;
class UTextBlock;
class UUniformGridPanel;
class UVerticalBox;
class UWidgetSwitcher;

DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(
	FHyperTwistFirstRunRouteRequestedSignature,
	const FString&,
	RouteId
);

UENUM(BlueprintType)
enum class EHyperTwistMainMenuPage : uint8
{
	Home,
	Puzzles,
	Learn,
	Settings,
	Account,
	Advanced,
	About
};

UCLASS()
class UNREALHYPERTWIST_API UHyperTwistPuzzleCardWidget : public UUserWidget
{
	GENERATED_BODY()

public:
	UFUNCTION(BlueprintCallable, Category = "HyperTwist|MainMenu")
	void ConfigureCatalogEntry(const FHyperTwistPuzzleCatalogEntry& InEntry);

	UPROPERTY(BlueprintAssignable, Category = "HyperTwist|MainMenu")
	FHyperTwistFirstRunRouteRequestedSignature OnLaunchRequested;

protected:
	virtual TSharedRef<SWidget> RebuildWidget() override;

private:
	void EnsureWidgetTreeBuilt();
	void RefreshFromCatalogEntry();

	UFUNCTION()
	void HandleLaunchClicked();

	FHyperTwistPuzzleCatalogEntry Entry;
	FString ActionId;

	UPROPERTY(Transient)
	TObjectPtr<UTextBlock> AvailabilityText = nullptr;

	UPROPERTY(Transient)
	TObjectPtr<UTextBlock> TitleText = nullptr;

	UPROPERTY(Transient)
	TObjectPtr<UTextBlock> DescriptionText = nullptr;

	UPROPERTY(Transient)
	TObjectPtr<UTextBlock> TagsText = nullptr;

	UPROPERTY(Transient)
	TObjectPtr<UButton> LaunchButton = nullptr;

	UPROPERTY(Transient)
	TObjectPtr<UTextBlock> LaunchButtonText = nullptr;
};

UCLASS(BlueprintType, Blueprintable)
class UNREALHYPERTWIST_API UHyperTwistFirstRunLaunchWidget
	: public UUserWidget
{
	GENERATED_BODY()

public:
	virtual void NativeOnInitialized() override;
	virtual void NativeConstruct() override;
	virtual void NativeDestruct() override;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist|FirstRun")
	FLinearColor BackgroundColor = FLinearColor(0.007f, 0.012f, 0.021f, 1.0f);

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist|FirstRun")
	FLinearColor PanelColor = FLinearColor(0.018f, 0.030f, 0.047f, 0.985f);

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist|FirstRun")
	FLinearColor CardColor = FLinearColor(0.034f, 0.054f, 0.078f, 0.98f);

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist|FirstRun")
	FLinearColor AccentColor = FLinearColor(0.0f, 0.88f, 0.78f, 1.0f);

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist|FirstRun")
	FLinearColor WarmAccentColor = FLinearColor(1.0f, 0.62f, 0.22f, 1.0f);

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist|FirstRun")
	FLinearColor TextColor = FLinearColor(0.91f, 0.96f, 0.98f, 1.0f);

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist|FirstRun")
	FLinearColor MutedTextColor = FLinearColor(0.58f, 0.70f, 0.76f, 1.0f);

	UPROPERTY(BlueprintAssignable, Category = "HyperTwist|FirstRun")
	FHyperTwistFirstRunRouteRequestedSignature OnFirstRunRouteRequested;

	UFUNCTION(BlueprintCallable, Category = "HyperTwist|FirstRun")
	void RebuildFirstRunLaunchSurface();

	UFUNCTION(BlueprintPure, Category = "HyperTwist|FirstRun")
	bool IsFirstRunLaunchSurfaceReady() const;

	UFUNCTION(BlueprintCallable, Category = "HyperTwist|MainMenu")
	void ShowPage(EHyperTwistMainMenuPage Page);

protected:
	virtual TSharedRef<SWidget> RebuildWidget() override;
	virtual FReply NativeOnKeyDown(
		const FGeometry& InGeometry,
		const FKeyEvent& InKeyEvent
	) override;

	UFUNCTION()
	void OpenCoachDashboard();

	UFUNCTION()
	void OpenClassicCubeTraining();

	UFUNCTION()
	void OpenFollowAlongTraining();

	UFUNCTION()
	void OpenMagic120CellTraining();

	UFUNCTION()
	void OpenMagicCube5DTraining();

	UFUNCTION()
	void OpenXrTrainingValidation();

private:
	UHyperTwistTrainingSubsystem* ResolveTrainingSubsystem() const;
	void StartLearningProgram(const FString& ProgramTitle, const FString& DeckId);
	void SubmitLearningStudioAttempt(bool bRemembered);
	void RefreshLearningStudioSurface(const FString& StatusMessage = FString(), bool bError = false);
	void RequestRoute(const FString& RouteId);
	void BuildNavigation(UVerticalBox* NavigationColumn);
	void BuildHomePage(UVerticalBox* Page);
	void BuildPuzzlePage(UVerticalBox* Page);
	void BuildLearnPage(UVerticalBox* Page);
	void BuildSettingsPage(UVerticalBox* Page);
	void BuildAccountPage(UVerticalBox* Page);
	void BuildAdvancedPage(UVerticalBox* Page);
	void BuildAboutPage(UVerticalBox* Page);
	void RefreshAccountSurface(const FString& StatusMessage = FString(), bool bError = false);
	void ProcessDesktopLinkResponse(bool bConnectedSuccessfully, int32 StatusCode, const FString& Body);
	void OpenExternalUrl(const FString& Url) const;

	UTextBlock* AddTextLine(
		UVerticalBox* Parent,
		const FString& Text,
		int32 FontSize,
		const FLinearColor& Color,
		const FName& WidgetName = NAME_None
	) const;
	UButton* AddNavigationButton(
		UVerticalBox* Parent,
		const FString& Label,
		const FName& ButtonName
	) const;
	UButton* AddActionButton(
		UVerticalBox* Parent,
		const FString& Label,
		const FString& SupportingText,
		const FName& ButtonName,
		bool bPrimary = false
	) const;
	UVerticalBox* AddPage(
		const FName& PageName,
		const FString& Eyebrow,
		const FString& Title,
		const FString& Description
	);
	void AddFeatureCard(
		UVerticalBox* Parent,
		const FString& Eyebrow,
		const FString& Title,
		const FString& Description,
		const FLinearColor& Accent
	) const;
	void AddSpacer(UVerticalBox* Parent, float Height) const;

	UFUNCTION()
	void ShowHomePage();

	UFUNCTION()
	void ShowPuzzlesPage();

	UFUNCTION()
	void ShowLearnPage();

	UFUNCTION()
	void ShowSettingsPage();

	UFUNCTION()
	void ShowAccountPage();

	UFUNCTION()
	void ShowAdvancedPage();

	UFUNCTION()
	void ShowAboutPage();

	UFUNCTION()
	void HandleCatalogLaunchRequested(const FString& RouteId);

	UFUNCTION()
	void HandleStartOllLearningProgram();

	UFUNCTION()
	void HandleStartCrossLearningProgram();

	UFUNCTION()
	void HandleStartFiveStyleLearningProgram();

	UFUNCTION()
	void HandleStartRouxLearningProgram();

	UFUNCTION()
	void HandleStartBlindfoldLearningProgram();

	UFUNCTION()
	void HandleRevealLearningAnswer();

	UFUNCTION()
	void HandleLearningRemembered();

	UFUNCTION()
	void HandleLearningReviewAgain();

	UFUNCTION()
	void HandleOpenAccountWebsite();

	UFUNCTION()
	void HandleOpenBrowserExperience();

	UFUNCTION()
	void HandleOpenHelpCenter();

	UFUNCTION()
	void HandleLinkAccount();

	UFUNCTION()
	void HandleUnlinkAccount();

	UFUNCTION()
	void HandleOpenDiagnosticsFolder();

	UFUNCTION()
	void HandleExitApplication();

	UPROPERTY(Transient)
	TObjectPtr<UWidgetSwitcher> PageSwitcher = nullptr;

	UPROPERTY(Transient)
	TObjectPtr<UTextBlock> CurrentPageTitle = nullptr;

	UPROPERTY(Transient)
	TObjectPtr<UTextBlock> AccountIdentityText = nullptr;

	UPROPERTY(Transient)
	TObjectPtr<UTextBlock> AccountAccessText = nullptr;

	UPROPERTY(Transient)
	TObjectPtr<UTextBlock> AccountStatusText = nullptr;

	UPROPERTY(Transient)
	TObjectPtr<UEditableTextBox> DesktopLinkTokenInput = nullptr;

	UPROPERTY(Transient)
	TObjectPtr<UButton> LinkAccountButton = nullptr;

	UPROPERTY(Transient)
	TObjectPtr<UButton> UnlinkAccountButton = nullptr;

	UPROPERTY(Transient)
	TObjectPtr<UTextBlock> LearningProgramText = nullptr;

	UPROPERTY(Transient)
	TObjectPtr<UTextBlock> LearningProgressText = nullptr;

	UPROPERTY(Transient)
	TObjectPtr<UTextBlock> LearningPromptText = nullptr;

	UPROPERTY(Transient)
	TObjectPtr<UTextBlock> LearningSetupText = nullptr;

	UPROPERTY(Transient)
	TObjectPtr<UTextBlock> LearningAnswerText = nullptr;

	UPROPERTY(Transient)
	TObjectPtr<UTextBlock> LearningStatusText = nullptr;

	UPROPERTY(Transient)
	TObjectPtr<UButton> LearningRevealButton = nullptr;

	UPROPERTY(Transient)
	TObjectPtr<UButton> LearningRememberedButton = nullptr;

	UPROPERTY(Transient)
	TObjectPtr<UButton> LearningReviewButton = nullptr;

	FString ActiveLearningProgramTitle;
	FString ActiveLearningDeckId;
	double LearningCaseStartedAtSeconds = 0.0;
	bool bLearningAnswerRevealed = false;

	UPROPERTY(Transient)
	TObjectPtr<UHyperTwistSettingsPanelWidget> EmbeddedSettings = nullptr;

	TSharedPtr<IHttpRequest, ESPMode::ThreadSafe> ActiveAccountRequest;
	EHyperTwistMainMenuPage ActivePage = EHyperTwistMainMenuPage::Home;
};
