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

using DXLib.UI.Card;
using DXLib.UI.Alert;
using DXLib.UI.Control;

using DXLib.Data;
using DXLib.Utils;

namespace iStatVball3;

/*
 * Card page for list of matches within a parent tournament or season.
 */
public class MatchPage : CardPage
{
	/* Fields */
	private readonly Tournament tournament;
	private readonly int day;

	private readonly bool tournParent;
	private bool filterTourn;

	// Purchase
	private PurchaseView purchaseView;

	/* Methods */
	public MatchPage( Season season, Tournament tournament, int day = 0 ) : base( season )
	{
		this.tournament = tournament;
		this.day = day;

		// Grouped under tournament?
		tournParent = (tournament != null);

		Title = DXString.Get( "match.plural" );

		// Matches sorted newest first
		ScrollPosition = ScrollToPosition.Start;
	}

	/* Abstracts */

	// Displays all match cards
	public override void LoadCards()
	{
		Clear();

		// Required for permissions
		User user = Shell.CurrentUser;

		// Build match list (season, tournament, or tournament day)
		List<Match> matches = GetMatches( true );

		if ( matches != null )
		{
			if ( data is Season season )
			{
				// Add card for each match
				foreach ( Match match in matches )
				{
					match.Populate( season );

					// Possibly hiding tournament matches
					if ( tournParent || (!filterTourn || (match.Tournament == null)) )
					{
						MatchCard card = new( match, tournParent )
						{
							HasAnalyze = true,

							IsEditEnabled = Match.CanEdit( user ),
							IsAnalyzeEnabled = Match.CanAnalyze() && !match.IsNew,

							IsTappable = true,

							CardTapped = OnCardTapped,
							AnalyzeTapped = OnAnalyzeTapped,
							EditTapped = OnEditTapped
						};

						card.Init();
						
						AddCard( card );
					}
				}

				// NA for tournament days
				bool canAdd = !tournParent || (day == 0);

				// Add card for creating new objects
				if ( canAdd && Match.CanCreate( season, user ) )
				{
					AddNewCard( "match", CardSmall.CardHt );
				}
			}
		}
	}

	// Returns list of matches for page (season, tournament, or tournament day)
	private List<Match> GetMatches( bool sorted )
	{
		List<Match> matches = null;

		filterTourn = false;

		// Normal match list
		if ( tournament == null )
		{
			if ( data is Season season )
			{
				matches = season.Matches;
				filterTourn = Shell.Settings.GeneralFilter;
			}
		}
		// Tournament matches (single or multi-day)
		else
		{
			matches = (day == 0) ? tournament.Matches : tournament.MatchesForDay( day );
		}

		// Optionally sort newest matches first
		return sorted ? matches?.OrderByDescending( m => m.MatchTime ).ToList() : matches;
	}

	/* Event Callbacks */

	// Called back when 'Add New' tapped
	protected override async void OnNewCardTapped( DXCard card )
	{
        User user = Shell.CurrentUser;

		// Admin always OK to proceed
		if ( user.IsAdmin )
		{
			OnCreate();
			return;
		}

		if ( data is Season season )
		{
			string purchaseId = season.PurchaseId;

			// Should not happen
			if ( purchaseId == null )
			{
				DXAlert.ShowError( "purchase.title", "purchase.err.season", OnCancelled );
			}
			// Season started under free trial
			else if ( purchaseId == Purchase.FreeTrialId )
			{
				// Still in trial, OK to proceed
				if ( PurchaseEngine.IsTrialPeriod( user ) )
				{
					OnCreate();
				}
				// Expired
				else
				{
					string allocateId = await PurchaseEngine.Allocate( user );

					// Already purchased, allocate to season, OK to proceed
					if ( (allocateId != null) && (allocateId != Purchase.FreeTrialId) )
					{
						await season.UpdatePurchase( allocateId );

						OnCreate();
					}
					// Need to purchase
					else
					{
						DXAlert.ShowOkCancel( "purchase.end", "purchase.end.msg2", OnConfirmed, OnCancelled );
					}
				}
			}
			// Purchased, OK to proceed
			else
			{
				OnCreate();
			}
		}
	}

	// Proceed with match creation
	private void OnCreate()
	{
		if ( data is Season season )
		{
			// How long since season started?
			TimeSpan elapsed = DateTimeOffset.Now.Subtract( season.Created );

			// Season cannot go beyond 1 year
			if ( (elapsed.TotalDays > 365) && !Shell.CurrentUser.IsAdmin )
			{
				DXAlert.ShowError( "purchase.title", "purchase.err.year", OnCancelled );
			}
			// OK to proceed
			else
			{
				MatchForm form = new( null, tournament, season );

				// Open in create mode
				Shell.Instance.ShowForm( form );
			}
		}
	}

	// User confirmed start of purchase flow
	private async void OnConfirmed()
	{
		purchaseView = new PurchaseView()
		{
			Completed = OnCompleted,
			Cancelled = OnCancelled
		};
		
		await purchaseView.ShowProducts();
	}

	// User successfully completed purchase
	private async void OnCompleted()
	{
		if ( data is Season season )
		{
			User user = Shell.CurrentUser;
			
			// Get allocated purchase
			string purchaseId = await PurchaseEngine.Allocate( user );
			
			// Save to existing season
			await season.UpdatePurchase( purchaseId );
			
			purchaseView.Hide();
			
			OnCreate();
		}
	}

	// User cancelled purchase flow
	private void OnCancelled()
	{
		DXSpinner.Stop();

		Reset();
	}

	// Called back when normal card tapped
	private void OnCardTapped( DXCard card )
	{
		if ( card.Data is Match match )
		{
			SetPage page = new( match );
			
			// Navigate to sets page for selected match
			Shell.Instance.PageStack.Push( page, match.Name );
		}
	}

	// Called back when card analyze button tapped
	private async void OnAnalyzeTapped( DXCard card )
	{
		if ( (card.Data is Match match) && (data is Season season) )
		{
			Shell shell = Shell.Instance;

			// Init dashboard with aggregated data
			shell.DashboardForm.Init( new DashboardConfig
			{
				Scope = DataConfig.MatchScope,
				ScopeName = match.VsName,
				ScopeObject = match,

				Organization = season.Team.Organization,

				Team1 = match.Team1,
				Team2 = match.Opponent
			} );

			bool sync = DXData.HasConnection() && match.IsInProgress && !Shell.CurrentUser.IsRecording;

			// Show with optional sync button
			await shell.ShowDashboardForm( match.VsName, sync );
		}
	}

	// Called back when card edit button tapped
	private void OnEditTapped( DXCard card )
	{
		Match match = card.Data as Match;
		Season season = data as Season;

		MatchForm form = new( match, tournament, season );

		// Open in edit mode
		Shell.Instance.ShowForm( form );
	}
}

//
