/*
 * Copyright (c)2009-2025 DemiVision, LLC. All Rights Reserved. The information
 * herein is the CONFIDENTIAL and PROPRIETARY information of DemiVision, LLC.
 */

using Plugin.Firebase.Auth;

using DXLib.UI;
using DXLib.UI.Alert;
using DXLib.UI.Layout;
using DXLib.UI.Form.Message;

using DXLib.UI.Control;
using DXLib.UI.Control.Button;

using DXLib.Email;
using DXLib.Data;
using DXLib.Utils;

namespace iStatVball3;

/*
 * Displays 'Sign In' screen and handles all data input and validation for the screen. The remote login process is
 * started from here.
 */
public class LaunchLogin : LaunchPage
{
	/* Constants */

	// Max login try (ms)
	private const int LoginTimeout = (60 * 1000);

	/* Fields */
	private readonly DXGridLayout outerLayout;
	private readonly DXVerticalLayout innerLayout;

	private readonly LaunchLoginForm form;

	private readonly DXIcon titleIcon;
	private readonly DXLabel titleLbl;
	private readonly DXTextButton forgotBtn;
	private readonly DXButton loginBtn;

	/* Methods */
	public LaunchLogin( string username )
	{
		BackgroundColor = DXColors.Dark1;

		// Main layout
		outerLayout = new DXGridLayout
		{
			Padding = 0,
			RowSpacing = 0,
			ColumnSpacing = 0
		};

		// Centers everything within main layout
		innerLayout = new DXVerticalLayout
		{
			Horizontal = LayoutOptions.Center,
			Vertical = LayoutOptions.Center,
		};

		// 'Sign In'
		DXHorizontalLayout titleLayout = new()
		{
			Spacing = 15,

			Margin = new Thickness( 0, 0, 0, 20 ),
			Horizontal = LayoutOptions.Center
		};

		titleIcon = new DXIcon
		{
			Resource = "account_circle",
			Color = DXColors.Light4,

			Horizontal = LayoutOptions.Center,
			Vertical = LayoutOptions.Center
		};

		titleLayout.Add( titleIcon );

		string title = DXString.Get( "login.title" );

		titleLbl = new DXLabel
		{
			Text = title,
			TextColor = DXColors.Light4,

			Font = DXFonts.Roboto,

			Horizontal = LayoutOptions.Center,
			Vertical = LayoutOptions.Center
		};

		titleLayout.Add( titleLbl );

		innerLayout.Add( titleLayout );

		// Data fields
		form = new LaunchLoginForm
		{
			Username = username,

			Margin = new Thickness( 0, -25, 0, 0 ),

			Horizontal = LayoutOptions.Center,
			Vertical = LayoutOptions.Start
		};

		innerLayout.Add( form );

		// 'Forgot password?'
		forgotBtn = new DXTextButton
		{
			Text = DXString.Get( "login.forgot" ),
			Color = DXColors.Action,
			
			Font = DXFonts.Roboto,
			FontSize = 15,

			Margin = DXUtils.Left( -5 ),

			Horizontal = LayoutOptions.Center,
			ButtonTapped = OnForgotTapped
		};

		innerLayout.Add( forgotBtn );

		// 'Sign In'
		loginBtn = new DXButton
		{
			Resource = "login.title",
			Type = DXButton.ButtonType.Positive,

			ButtonWd = 230,
			ButtonHt = 48,

			Horizontal = LayoutOptions.Center,
			ButtonTapped = OnLoginTapped,
			
			IsDisabled = true				// MUST be last
		};

		loginBtn.Init();
		
		innerLayout.Add( loginBtn );
		outerLayout.Add( innerLayout, 1, 0 );

		Content = outerLayout;

		// Update appbar
		Shell.Instance.AppBar.Title = title;

		// Start listening for control changes
		Start();
	}

	// Sends welcome email, displays welcome alerts, following first login
	private static async Task HandleFirstLogin( User user )
	{
		// Send welcome email
		await DXEmail.Send( new DXEmailConfig
		{
			FromAddress = DXString.Get( "email.address" ),
			FromName = DXString.Get( "email.name" ),
		
			ToAddress = user.Username,
			ToName = user.FirstName,
		
			TemplateId = LaunchEmail.TemplateId,
			TemplateData = new LaunchEmail
			{
				FirstName = user.FirstName,
				Level = user.RoleName
			}
		});

		string key = (user.Level >= User.LevelType.Coach) ? "coach" : "other";

		// Welcome user
		DXAlert.ShowOk( "welcome.help", $"welcome.help.{key}", OnWelcomeConfirmed );
	}
	
	/* Event Callbacks */

	// Displays 'Did You Know?' RallyFlow/Legacy engine alert
	private static void OnWelcomeConfirmed()
	{
		DXAlert.ShowOk( "welcome.engine", "welcome.engine.msg" );
	}

	// Start remote login process
	private async void OnLoginTapped( object sender )
	{
		// Hide keyboard before leaving screen
		await form.HideKeyboard();
		
		string username = form.Username;
		string password = form.Password;

		// Validate email/password
		if ( DXEmailUtils.IsValid( username ) && !string.IsNullOrEmpty( password ) )
		{
			// Validate connection
			if ( DXData.HasConnection() )
			{
				DXSpinner.Start();

				// Wait until callback
				DXAuth.Login( username, password, OnLoginCompleted );
			}
			else
			{
				DXAlert.ShowNetworkError( "net.err.account" );
			}
		}
		else
		{
			DXAlert.ShowError( "login.err", "login.err.empty" );
		}
	}

	// Login complete, either successfully or with error
	private async void OnLoginCompleted( DXAuth.AuthResult result, string resultStr, IFirebaseUser authUser )
	{
		// Success
		if ( result == DXAuth.AuthResult.Success )
		{
			bool timeout = false;

			// Enforce timeout for sync process
			DXTimer timer = DXTimer.Delay( LoginTimeout, () =>
			{
				timeout = true;
				LaunchStack.HandleTimeout();
			});

			// Find db user
			User user = await User.ReadByAuth( resultStr );

			// Email verification not required in older builds
			if ( (user != null) && (authUser.IsEmailVerified || (user.Version < 3)) )
			{
																														DXProfiler.Start( true );
				bool firstLogin = (user.LastLogin == null);

				// Perform login tasks
				await user.Login();
				
				// Proceed to main UI
				if ( !timeout )
				{
					timer.Stop();
																														DXProfiler.Mark( "Login" );
					Stop();

					await LaunchStack.TransitionToMain( user );

					// Additional functionality ONLY on first login
					if ( firstLogin )
					{
						await HandleFirstLogin( user );
					}
				}
			}
			else
			{
				DXSpinner.Stop();

				// Account deleted
				if ( user == null )
				{
					DXAlert.ShowError( "login.err", "login.err.invalid" );
				}
				// Email not verified
				else
				{
					string email = user.Username;
					string title = DXString.Get( "login.err" );
					string msg = DXString.Get( "login.err.verify", email );

					DXAlert.ShowPositiveCancelRaw( title, msg, "login.resend", () => { OnResendTapped( authUser, email ); } );
				}
			}
		}
		// Error
		else
		{
			switch ( result )
			{
				// Bad account/password
				case DXAuth.AuthResult.ErrorNotFound:
				case DXAuth.AuthResult.ErrorPassword:
				{
					DXAlert.ShowError( "login.err", "login.err.invalid" );
					break;
				}
				// Timeout
				case DXAuth.AuthResult.ErrorTimeout:
				{
					DXAlert.ShowError( "login.err", "login.err.timeout" );
					break;
				}
				// Unknown error
				default:
				{
					DXAlert.ShowError( "login.err", "login.err.unknown", resultStr );
					break;
				}
			}

			DXSpinner.Stop();
		}
	}

	// User tapped resend button, send another verification email
	private static void OnResendTapped( IFirebaseUser authUser, string email )
	{
		DXAuth.VerifyEmail( authUser );

		string title = DXString.Get( "login.resend" );
		string msg = DXString.Get( "login.verify", email );

		DXAlert.ShowOkRaw( title, msg );
	}

	// User tapped 'Forgot Password?' link
	private void OnForgotTapped( object sender )
	{
		string email = form.Username;

		DXSpinner.Start();

		// Must enter email first
		if ( string.IsNullOrEmpty( email ) || !DXEmailUtils.IsValid( email ) )
		{
			DXAlert.ShowOk( "login.reset.title", "login.reset.err", forgotBtn.Reset );

			DXSpinner.Stop();
		}
		// Request reset, wait for result
		else
		{
			DXAuth.ResetPassword( email, OnPasswordReset );
		}
	}

	// Reset request completed, either successfully or with error
	private static void OnPasswordReset( DXAuth.AuthResult result )
	{
		// Success
		if ( result == DXAuth.AuthResult.Success )
		{
			DXAlert.ShowOk( "login.reset.title", "login.reset.msg" );
		}
		// Error
		else
		{
			switch ( result )
			{
				// Account not found
				case DXAuth.AuthResult.ErrorNotFound:
				{
					DXAlert.ShowError( "login.reset.title", "login.reset.err.invalid" );
					break;
				}
				// Unknown error
				default:
				{
					DXAlert.ShowNeutral( "login.reset.title", "login.err.unknown" );
					break;
				}
			}
		}

		DXSpinner.Stop();
	}

	// Login button disabled if any fields not valid
	protected override void OnControlChanged( object sender, DXFormChangedMessage msg )
	{
		loginBtn.IsDisabled = !form.IsValid();
	}

	/* Layout */

	// Layout common to all orientations
	public override void UpdateLayout( LayoutType type )
	{
		outerLayout.Clear();

		Padding = 0;
		
		// Default sizing
		innerLayout.Spacing = 24;

		titleIcon.Size = 36;
		titleLbl.FontSize = 36;

		loginBtn.WidthRequest = 110;
		loginBtn.HeightRequest = 48;

		// Size specific layouts
		base.UpdateLayout( type );

		// Update children
		form.UpdateLayout( type );
	}

	// Landscape
	protected override void Landscape()
	{
		outerLayout.AddStarColumn( 25 );
		outerLayout.AddStarColumn( 50 );
		outerLayout.AddStarColumn( 25 );
	}

	// Portrait
	protected override void Portrait()
	{
		outerLayout.AddStarColumn( 20 );
		outerLayout.AddStarColumn( 60 );
		outerLayout.AddStarColumn( 20 );
	}

	// Mobile landscape
	protected override void MobileLandscape()
	{
		Padding = new Thickness( 0, 10, 0, 0 );
		
		innerLayout.Spacing = 16;

		titleIcon.Size = 28;
		titleLbl.FontSize = 28;

		loginBtn.WidthRequest = 100;
		loginBtn.HeightRequest = 42;

		outerLayout.AddFixedColumn( 5 );
		outerLayout.AddStarColumn();
		outerLayout.AddFixedColumn( 5 );
	}
	
	// Mobile portrait
	protected override void MobilePortrait()
	{
		innerLayout.Spacing = 16;

		titleIcon.Size = 28;
		titleLbl.FontSize = 28;

		loginBtn.WidthRequest = 100;
		loginBtn.HeightRequest = 42;

		outerLayout.AddFixedColumn( 5 );
		outerLayout.AddStarColumn();
		outerLayout.AddFixedColumn( 5 );
	}
}

//
