public async Task CreateNewTeamRankingAsync(Team team, Season season)
        {
            if (team == null)
            {
                throw new ArgumentNullException(nameof(team));
            }
            if (season == null)
            {
                throw new ArgumentNullException(nameof(season));
            }

            // Find the worst rank in the basic bracket
            var neverLucky = await _db.RankBrackets
                    .Include(x => x.Season)
                    .SingleOrDefaultAsync(x => x.Type == RankBrackets.NeverLucky && x.Season.SeasonId == season.SeasonId);

            if (neverLucky == null)
            {
                throw new InvalidProgramException("Unable to load baseline bracket for new team");
            }

            var rank = new Rank
            {
                RankBracket = neverLucky,
                Rating = new Rating { MatchMakingRating = 1500 }
            };

            team.Rank = rank;

            _db.Add(rank);
            _db.Add(rank.Rating);
            _db.Update(team);

            await _db.SaveChangesAsync();
        }
        public async Task CreateDefaultImageForTeamAsync(Team team)
        {
            var image = await GetDefaultImageAsync(Defaults.TeamImage);
            team.TeamImage = image;

            _db.Update(team);

            await _db.SaveChangesAsync();
        }
        public async Task NotifyTeamInvite(Team team)
        {
            if (team == null)
            {
                throw new ArgumentNullException(nameof(team));
            }
            if (team.Invitees == null)
            {
                throw new ArgumentNullException(nameof(team.Invitees));
            }

            foreach (var invitee in team.Invitees)
            {
                if (invitee.Player != null && invitee.Player.User != null)
                {
                    var notification = new Notification
                    {
                        Message = string.Format(TeamInviteMessage, team.Name),
                        Title = TeamInviteTitle,
                        User = invitee.Player.User
                    };

                    try
                    {
                        _db.Add(notification);
                        await _db.SaveChangesAsync();
                    }
                    catch (Exception e)
                    {
                        _logger.LogWarning($"Failed to notify {invitee.Player.User.UserName} of team invite to {team.Name}", e);
                    }

                    if (invitee.Player.User.EmailNotifications)
                    {
                        await _emailService.SendAsync(invitee.Player.User.Email, TeamInviteMessage);
                    }
                }
            }
        }
        public async Task UpdateBannerImageAsync(Team team, string data)
        {
            if (team == null)
            {
                throw new ArgumentNullException(nameof(team));
            }

            if (string.IsNullOrEmpty(data))
            {
                throw new ArgumentNullException(nameof(data));
            }

            var bytes = GetImageBytes(data);
            var relativePath = BuildImagePath("teams", team.NormalizedName, data);

            var image = await UpdateImageAsync(team.HeaderImage, Defaults.HeaderImage, relativePath, bytes);
            if (image.ImageId <= 0)
            {
                _db.Add(image);
            }

            team.HeaderImage = image;
            _db.Attach(team);

            await _db.SaveChangesAsync();
        }
        public async Task<TeamResult> CreateTeamAsync(ClaimsPrincipal signedInUser, DataTransferObjects.Team team)
        {
            // Validate team
            if (team == null)
            {
                throw new ArgumentNullException(nameof(team));
            }
            if (team.Roster == null)
            {
                throw new ArgumentNullException(nameof(team.Roster));
            }
            if (team.Roster.Count() < 5)
            {
                throw new InvalidOperationException("Teams must have at least 5 members.");
            }
            if (team.Owner == null)
            {
                throw new ArgumentNullException(nameof(team.Owner));
            }
            if (string.IsNullOrEmpty(team.Owner.Username))
            {
                throw new InvalidOperationException("Team owner invalid username");
            }
            if (string.IsNullOrEmpty(team.Name))
            {
                throw new ArgumentNullException(nameof(team.Name));
            }
            if (!Team.TeamNameRegex.IsMatch(team.Name))
            {
                throw new InvalidOperationException($"Team name {team.Name} is invalid");
            }

            // Make sure we have a default season
            var season = await _seasonManager.GetCurrentSeasonAsync();
            if (season == null)
            {
                throw new InvalidProgramException("Current season not found");
            }

            var entity = new Team { Name = team.Name, NormalizedName = team.Name.ToLower().Replace(' ', '-') };

            // Create team roster
            var roster = new List<TeamInvite>();
            foreach (var invitee in team.Roster)
            {
                // Validate invitee
                if (string.IsNullOrEmpty(invitee.Username) && string.IsNullOrEmpty(invitee.Tag))
                {
                    throw new InvalidOperationException("Team roster invalid");
                }

                if (invitee.Username != team.Owner.Username)
                {
                    Player player = null;

                    if (!string.IsNullOrEmpty(invitee.Username))
                    {
                        // If the player has a username, load the user
                        player = _db.Players
                            .Include(x => x.User)
                            .SingleOrDefault(x => x.User.UserName == invitee.Username);
                        if (player == null)
                        {
                            throw new InvalidProgramException($"Player entity for user {invitee.Username} not found.");
                        }
                    }
                    else
                    {
                        player = await _db.Players.FirstOrDefaultAsync(x => x.Tag == invitee.Tag);
                    }

                    if (player == null)
                    {
                        throw new InvalidProgramException($"Unable to find player");
                    }

                    var invite = new TeamInvite { Player = player, Team = entity };
                    roster.Add(invite);
                }
            }

            // Create team owner
            var ownerPlayer = _db.Players
                .Include(x => x.User)
                .SingleOrDefault(x => x.User.UserName == team.Owner.Username);
            if (ownerPlayer == null)
            {
                throw new InvalidProgramException($"Player entity for owner {team.Owner.Username} not found.");
            }
            if (ownerPlayer.User.Id != signedInUser.GetUserId())
            {
                throw new InvalidOperationException($"Team owner must be currently signed in user.");
            }

            var teamOwner = new TeamOwner { Player = ownerPlayer, Team = entity };

            // Begin transaction as this is where we begin save operations
            var transaction = await _db.Database.BeginTransactionAsync();

            var result = await _userManager.AddClaimAsync(ownerPlayer.User, new Claim($"{AuthorizationDefaults.ClaimTypeTeamOwner}:{entity.NormalizedName}", ownerPlayer.User.UserName));
            EnsureIdentitySucceeded(result);

            // Refresh the signin to add the owner cookie
            await _signInManager.RefreshSignInAsync(ownerPlayer.User);

            entity.Invitees = roster;
            entity.Owner = teamOwner;

            _db.Add(teamOwner);
            _db.Add(entity);
            foreach (var invitee in roster)
            {
                _db.Add(invitee);
            }

            try
            {
                await _db.SaveChangesAsync();

                // Setup rank & image
                await _rankManager.CreateNewTeamRankingAsync(entity, season);
                await _imageManager.CreateDefaultImageForTeamAsync(entity);
            }
            catch (Exception e)
            {
                transaction.Rollback();

                return TeamResult.Failed(e);
            }

            transaction.Commit();

            return TeamResult.Success(entity);
        }
 public Task<Team> UpdateTeamOwner(Team team, string newOwner)
 {
     throw new NotImplementedException();
 }