using Endpoint;
using LocalEndpoint.Data;
using Models;
using System.Collections.Immutable;

namespace LocalEndpoint
{
    internal class AccountRecipesPreferences : IAccountRecipesPreferences
    {

        private readonly Database db;
        public AccountRecipesPreferences(Account account, Database db)
        {
            Account = account;
            this.db = db;
        }

        public Account Account { get; init; }

        public ImmutableList<RecipeInfo> GetRecommendedRecipes()
        {
            return db.ListAllRecipes().ConvertAll(recipe => recipe.Info);
        }

        public ImmutableList<RecipeInfo> GetFavorites()
        {
            List<RecipeInfo> favorites = new List<RecipeInfo>();
            var ratings = db.ListRatesOf(Account.User.Id);

            foreach (Recipe recipe in db.ListAllRecipes())
            {
                if (ratings.TryGetValue(recipe.Info.Id, out RecipeRate? rate))
                {
                    if (rate.IsFavorite) 
                        favorites.Add(recipe.Info);
                }
            }
            return favorites.ToImmutableList();
        }

        public ImmutableList<(RecipeInfo, uint)> GetWeeklyList()
        {
            var weeklyDict = db.GetRecipeListOf(Account.User.Id);
            List<(RecipeInfo, uint)> weekly = new List<(RecipeInfo, uint)>();

            foreach (Recipe recipe in db.ListAllRecipes())
            {
                if (weeklyDict.TryGetValue(recipe.Info.Id, out uint personAmmount))
                {
                    weekly.Add((recipe.Info, personAmmount));
                }
            }
            return weekly.ToImmutableList();
        }

        
        public RecipeRate GetRate(RecipeInfo info)
        {
            RecipeRate rate = null;
            var ratings = db.ListRatesOf(Account.User.Id);

            if (!ratings.TryGetValue(info.Id, out rate))
            {
                rate = new RecipeRate();
                ratings.Add(info.Id, rate);
            }
            return rate;
        }

        public bool AddToWeeklyList(RecipeInfo info, uint persAmount)
        {
            var weeklyDict = db.GetRecipeListOf(Account.User.Id);
            if (weeklyDict.ContainsKey(info.Id))
                return false;

            db.InsertInUserList(Account.User.Id, info.Id, persAmount);

            return true;
        }


        public void AddToFavorites(RecipeInfo info)
        {
            Guid userId = Account.User.Id;
            var ratings = db.ListRatesOf(userId);
            RecipeRate rate = GetRate(info);

            db.InsertRate(userId, info.Id, new RecipeRate(true, rate.Rate));
        }

        public void RemoveFromFavorites(RecipeInfo info)
        {
            Guid userId = Account.User.Id;
            var ratings = db.ListRatesOf(userId);
            RecipeRate rate = GetRate(info);

            db.InsertRate(userId, info.Id, new RecipeRate(false, rate.Rate));
        }

        public void SetReviewScore(RecipeInfo info, uint score)
        {
            Guid userId = Account.User.Id;
            var ratings = db.ListRatesOf(userId);
            RecipeRate rate = GetRate(info);

            db.InsertRate(userId, info.Id, new RecipeRate(rate.IsFavorite, score));
        }
    }
}
