#pragma once

#include "CoreMinimal.h"
#include "Blueprint/UserWidget.h"
#include "HyperTwistUX/HyperTwistPlayerSettings.h"

#include "HyperTwistSettingsPanelWidget.generated.h"

class UButton;
class UCheckBox;
class UComboBoxString;
class UEditableTextBox;
class UHorizontalBox;
class USlider;
class UTextBlock;
class UUniformGridPanel;
class UVerticalBox;
class UWidgetSwitcher;

DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(
	FHyperTwistRebindRequestedSignature,
	FName,
	ActionId
);

DECLARE_DYNAMIC_MULTICAST_DELEGATE(FHyperTwistSettingsCloseRequestedSignature);

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

public:
	UFUNCTION(BlueprintCallable, Category = "HyperTwist|Settings|Controls")
	void ConfigureBinding(
		FName InActionId,
		const FString& InLabel,
		const FString& InCategory,
		FKey InKey
	);

	UFUNCTION(BlueprintCallable, Category = "HyperTwist|Settings|Controls")
	void UpdateBoundKey(FKey InKey, bool bAwaitingInput = false);

	UPROPERTY(BlueprintAssignable, Category = "HyperTwist|Settings|Controls")
	FHyperTwistRebindRequestedSignature OnRebindRequested;

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

private:
	void EnsureWidgetTreeBuilt();

	UFUNCTION()
	void HandleRebindClicked();

	FName ActionId;
	FString DisplayLabel;
	FString CategoryLabel;
	FKey BoundKey;

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

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

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

public:
	UHyperTwistSettingsPanelWidget(const FObjectInitializer& ObjectInitializer);

	virtual void NativeConstruct() override;

	UFUNCTION(BlueprintCallable, Category = "HyperTwist|Settings")
	bool PrepareSettingsSurface();

	UFUNCTION(BlueprintPure, Category = "HyperTwist|Settings")
	bool IsSettingsSurfaceReady() const;

	UFUNCTION(BlueprintCallable, Category = "HyperTwist|Settings")
	void ReloadPreferences();

	UPROPERTY(BlueprintAssignable, Category = "HyperTwist|Settings")
	FHyperTwistSettingsCloseRequestedSignature OnCloseRequested;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist|Settings|Style")
	bool bShowCloseButton = true;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist|Settings|Style")
	FLinearColor PanelColor = FLinearColor(0.020f, 0.031f, 0.050f, 0.985f);

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist|Settings|Style")
	FLinearColor CardColor = FLinearColor(0.038f, 0.060f, 0.087f, 1.0f);

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist|Settings|Style")
	FLinearColor AccentColor = FLinearColor(0.10f, 0.92f, 0.80f, 1.0f);

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist|Settings|Style")
	FLinearColor WarmAccentColor = FLinearColor(1.0f, 0.63f, 0.24f, 1.0f);

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist|Settings|Style")
	FLinearColor PrimaryTextColor = FLinearColor(0.93f, 0.97f, 1.0f, 1.0f);

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist|Settings|Style")
	FLinearColor MutedTextColor = FLinearColor(0.62f, 0.72f, 0.80f, 1.0f);

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

private:
	void EnsureWidgetTreeBuilt();
	void BuildControlsPage(UVerticalBox* Parent);
	void BuildAudioPage(UVerticalBox* Parent);
	void BuildGraphicsPage(UVerticalBox* Parent);
	void BuildAccessibilityPage(UVerticalBox* Parent);
	void BuildSpeechAndCoachPage(UVerticalBox* Parent);
	void RefreshWidgetsFromPreferences();
	void RefreshBindingRows();
	void RefreshMicrophoneOptions();
	void RefreshProviderReadiness();
	bool TryCompletePendingRebind(FKey PressedKey);
	void SavePreferencesAndApply(const FString& StatusMessage, bool bApplyGraphics = false);
	void SetStatus(const FString& Message, bool bError = false);

	UTextBlock* AddText(
		UVerticalBox* Parent,
		const FString& Text,
		int32 FontSize,
		const FLinearColor& Color,
		const FName& WidgetName = NAME_None
	);
	void AddSectionIntro(
		UVerticalBox* Parent,
		const FString& Eyebrow,
		const FString& Title,
		const FString& Description
	);
	UButton* AddTabButton(
		UUniformGridPanel* Parent,
		const FString& Label,
		int32 Column,
		const FName& WidgetName
	);
	UButton* AddActionButton(
		UHorizontalBox* Parent,
		const FString& Label,
		const FName& WidgetName,
		bool bPrimary = false
	);
	USlider* AddSliderRow(
		UVerticalBox* Parent,
		const FString& Label,
		const FString& SupportingText,
		const FName& WidgetName,
		TObjectPtr<UTextBlock>& OutValueLabel
	);
	UCheckBox* AddCheckRow(
		UVerticalBox* Parent,
		const FString& Label,
		const FString& SupportingText,
		const FName& WidgetName
	);
	UEditableTextBox* AddTextSetting(
		UVerticalBox* Parent,
		const FString& Label,
		const FString& SupportingText,
		const FName& WidgetName,
		bool bPassword = false
	);
	UComboBoxString* AddComboSetting(
		UVerticalBox* Parent,
		const FString& Label,
		const FString& SupportingText,
		const FName& WidgetName,
		const TArray<FString>& Options
	);
	UVerticalBox* AddScrollablePage(const FName& WidgetName);

	UFUNCTION()
	void ShowControlsPage();

	UFUNCTION()
	void ShowAudioPage();

	UFUNCTION()
	void ShowGraphicsPage();

	UFUNCTION()
	void ShowAccessibilityPage();

	UFUNCTION()
	void ShowSpeechAndCoachPage();

	UFUNCTION()
	void HandleCloseClicked();

	UFUNCTION()
	void HandleResetDefaultsClicked();

	UFUNCTION()
	void HandleBindingRequested(FName ActionId);

	UFUNCTION()
	void HandleKeyboardProfileChanged(
		FString SelectedItem,
		ESelectInfo::Type SelectionType
	);

	UFUNCTION()
	void HandlePointerSensitivityChanged(float Value);

	UFUNCTION()
	void HandleOrbitSensitivityChanged(float Value);

	UFUNCTION()
	void HandleZoomSensitivityChanged(float Value);

	UFUNCTION()
	void HandleInvertOrbitChanged(bool bChecked);

	UFUNCTION()
	void HandleTouchInputChanged(bool bChecked);

	UFUNCTION()
	void HandleMasterVolumeChanged(float Value);

	UFUNCTION()
	void HandleMusicVolumeChanged(float Value);

	UFUNCTION()
	void HandleEffectsVolumeChanged(float Value);

	UFUNCTION()
	void HandleVoiceVolumeChanged(float Value);

	UFUNCTION()
	void HandleMutedChanged(bool bChecked);

	UFUNCTION()
	void HandleGraphicsQualityChanged(
		FString SelectedItem,
		ESelectInfo::Type SelectionType
	);

	UFUNCTION()
	void HandleWindowModeChanged(
		FString SelectedItem,
		ESelectInfo::Type SelectionType
	);

	UFUNCTION()
	void HandleResolutionScaleChanged(float Value);

	UFUNCTION()
	void HandleVSyncChanged(bool bChecked);

	UFUNCTION()
	void HandleUiScaleChanged(float Value);

	UFUNCTION()
	void HandleReducedMotionChanged(bool bChecked);

	UFUNCTION()
	void HandleHighContrastChanged(bool bChecked);

	UFUNCTION()
	void HandleSubtitlesChanged(bool bChecked);

	UFUNCTION()
	void HandleSpeechInputChanged(bool bChecked);

	UFUNCTION()
	void HandleCoachNarrationChanged(bool bChecked);

	UFUNCTION()
	void HandleCloudProvidersChanged(bool bChecked);

	UFUNCTION()
	void HandleAssistantPanelEnabledChanged(bool bChecked);

	UFUNCTION()
	void HandleAssistantPanelOpenByDefaultChanged(bool bChecked);

	UFUNCTION()
	void HandleCoachAiEnabledChanged(bool bChecked);

	UFUNCTION()
	void HandleSpeechProviderChanged(
		FString SelectedItem,
		ESelectInfo::Type SelectionType
	);

	UFUNCTION()
	void HandleSpeechActivationModeChanged(
		FString SelectedItem,
		ESelectInfo::Type SelectionType
	);

	UFUNCTION()
	void HandleSpeechDictationDestinationChanged(
		FString SelectedItem,
		ESelectInfo::Type SelectionType
	);

	UFUNCTION()
	void HandleSpeechLanguageChanged(
		FString SelectedItem,
		ESelectInfo::Type SelectionType
	);

	UFUNCTION()
	void HandleSpeechEndpointCommitted(
		const FText& Text,
		ETextCommit::Type CommitMethod
	);

	UFUNCTION()
	void HandleSpeechModelCommitted(
		const FText& Text,
		ETextCommit::Type CommitMethod
	);

	UFUNCTION()
	void HandleSpeechMicrophoneChanged(
		FString SelectedItem,
		ESelectInfo::Type SelectionType
	);

	UFUNCTION()
	void HandleSpeechContextCommitted(
		const FText& Text,
		ETextCommit::Type CommitMethod
	);

	UFUNCTION()
	void HandleSpeechCleanupChanged(bool bChecked);

	UFUNCTION()
	void HandleSpeechSoundFeedbackChanged(bool bChecked);

	UFUNCTION()
	void HandleVoiceProviderChanged(
		FString SelectedItem,
		ESelectInfo::Type SelectionType
	);

	UFUNCTION()
	void HandleVoiceEndpointCommitted(
		const FText& Text,
		ETextCommit::Type CommitMethod
	);

	UFUNCTION()
	void HandleVoiceModelCommitted(
		const FText& Text,
		ETextCommit::Type CommitMethod
	);

	UFUNCTION()
	void HandleVoiceIdCommitted(
		const FText& Text,
		ETextCommit::Type CommitMethod
	);

	UFUNCTION()
	void HandleVoiceSpeedChanged(float Value);

	UFUNCTION()
	void HandleCoachProviderChanged(
		FString SelectedItem,
		ESelectInfo::Type SelectionType
	);

	UFUNCTION()
	void HandleCoachEndpointCommitted(
		const FText& Text,
		ETextCommit::Type CommitMethod
	);

	UFUNCTION()
	void HandleCoachModelCommitted(
		const FText& Text,
		ETextCommit::Type CommitMethod
	);

	UFUNCTION()
	void HandleCoachInstructionsCommitted(
		const FText& Text,
		ETextCommit::Type CommitMethod
	);

	UFUNCTION()
	void HandleCoachTemperatureChanged(float Value);

	UFUNCTION()
	void HandleCoachMaxResponseTokensChanged(float Value);

	UFUNCTION()
	void HandleCoachRequestTimeoutChanged(float Value);

	UFUNCTION()
	void HandleSaveSpeechCredential();

	UFUNCTION()
	void HandleRemoveSpeechCredential();

	UFUNCTION()
	void HandleSaveVoiceCredential();

	UFUNCTION()
	void HandleRemoveVoiceCredential();

	UFUNCTION()
	void HandleSaveCoachCredential();

	UFUNCTION()
	void HandleRemoveCoachCredential();

	UFUNCTION()
	void HandleValidateSpeechConfiguration();

	UFUNCTION()
	void HandleRefreshMicrophones();

	UFUNCTION()
	void HandleTestMicrophone();

	UFUNCTION()
	void HandleValidateVoiceConfiguration();

	UFUNCTION()
	void HandleValidateCoachConfiguration();

	FHyperTwistPlayerPreferences Preferences;
	FName PendingRebindActionId;
	bool bRefreshingWidgets = false;

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

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

	UPROPERTY(Transient)
	TObjectPtr<UComboBoxString> KeyboardProfileCombo = nullptr;

	UPROPERTY(Transient)
	TObjectPtr<USlider> PointerSensitivitySlider = nullptr;

	UPROPERTY(Transient)
	TObjectPtr<USlider> OrbitSensitivitySlider = nullptr;

	UPROPERTY(Transient)
	TObjectPtr<USlider> ZoomSensitivitySlider = nullptr;

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

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

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

	UPROPERTY(Transient)
	TObjectPtr<UCheckBox> InvertOrbitCheck = nullptr;

	UPROPERTY(Transient)
	TObjectPtr<UCheckBox> TouchInputCheck = nullptr;

	UPROPERTY(Transient)
	TObjectPtr<USlider> MasterVolumeSlider = nullptr;

	UPROPERTY(Transient)
	TObjectPtr<USlider> MusicVolumeSlider = nullptr;

	UPROPERTY(Transient)
	TObjectPtr<USlider> EffectsVolumeSlider = nullptr;

	UPROPERTY(Transient)
	TObjectPtr<USlider> VoiceVolumeSlider = nullptr;

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

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

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

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

	UPROPERTY(Transient)
	TObjectPtr<UCheckBox> MutedCheck = nullptr;

	UPROPERTY(Transient)
	TObjectPtr<UComboBoxString> GraphicsQualityCombo = nullptr;

	UPROPERTY(Transient)
	TObjectPtr<UComboBoxString> WindowModeCombo = nullptr;

	UPROPERTY(Transient)
	TObjectPtr<USlider> ResolutionScaleSlider = nullptr;

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

	UPROPERTY(Transient)
	TObjectPtr<UCheckBox> VSyncCheck = nullptr;

	UPROPERTY(Transient)
	TObjectPtr<USlider> UiScaleSlider = nullptr;

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

	UPROPERTY(Transient)
	TObjectPtr<UCheckBox> ReducedMotionCheck = nullptr;

	UPROPERTY(Transient)
	TObjectPtr<UCheckBox> HighContrastCheck = nullptr;

	UPROPERTY(Transient)
	TObjectPtr<UCheckBox> SubtitlesCheck = nullptr;

	UPROPERTY(Transient)
	TObjectPtr<UCheckBox> SpeechInputCheck = nullptr;

	UPROPERTY(Transient)
	TObjectPtr<UCheckBox> CoachNarrationCheck = nullptr;

	UPROPERTY(Transient)
	TObjectPtr<UCheckBox> CloudProvidersCheck = nullptr;

	UPROPERTY(Transient)
	TObjectPtr<UCheckBox> AssistantPanelEnabledCheck = nullptr;

	UPROPERTY(Transient)
	TObjectPtr<UCheckBox> AssistantPanelOpenByDefaultCheck = nullptr;

	UPROPERTY(Transient)
	TObjectPtr<UCheckBox> CoachAiEnabledCheck = nullptr;

	UPROPERTY(Transient)
	TObjectPtr<UComboBoxString> SpeechProviderCombo = nullptr;

	UPROPERTY(Transient)
	TObjectPtr<UComboBoxString> SpeechActivationModeCombo = nullptr;

	UPROPERTY(Transient)
	TObjectPtr<UComboBoxString> SpeechDictationDestinationCombo = nullptr;

	UPROPERTY(Transient)
	TObjectPtr<UComboBoxString> SpeechLanguageCombo = nullptr;

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

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

	UPROPERTY(Transient)
	TObjectPtr<UComboBoxString> SpeechMicrophoneCombo = nullptr;

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

	UPROPERTY(Transient)
	TObjectPtr<UCheckBox> SpeechCleanupCheck = nullptr;

	UPROPERTY(Transient)
	TObjectPtr<UCheckBox> SpeechSoundFeedbackCheck = nullptr;

	UPROPERTY(Transient)
	TObjectPtr<UComboBoxString> VoiceProviderCombo = nullptr;

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

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

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

	UPROPERTY(Transient)
	TObjectPtr<USlider> VoiceSpeedSlider = nullptr;

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

	UPROPERTY(Transient)
	TObjectPtr<UComboBoxString> CoachProviderCombo = nullptr;

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

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

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

	UPROPERTY(Transient)
	TObjectPtr<USlider> CoachTemperatureSlider = nullptr;

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

	UPROPERTY(Transient)
	TObjectPtr<USlider> CoachMaxResponseTokensSlider = nullptr;

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

	UPROPERTY(Transient)
	TObjectPtr<USlider> CoachRequestTimeoutSlider = nullptr;

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

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

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

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

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

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

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

	TArray<FHyperTwistMicrophoneDescriptor> AvailableMicrophones;

	UPROPERTY(Transient)
	TArray<TObjectPtr<UHyperTwistKeyBindingRowWidget>> BindingRows;
};
