using Endpoint;
using Models;
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace LocalEndpoint
{
    internal class AccountRecipesPreferences : IAccountRecipesPreferences
    {
        //Binds a recipe's id to it's account review ratings.
        private readonly Dictionary<Guid, AccountRecipeRate> ratings = new Dictionary<Guid, AccountRecipeRate>();

        //Binds a recipe's id to its amount of person stored in the account's weekly list
        private readonly Dictionary<Guid, uint> weekly = new Dictionary<Guid, uint>();

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

        public Account Account { get; init; }

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

        public ImmutableList<RecipeInfo> GetFavorites()
        {
            List<RecipeInfo> favorites = new List<RecipeInfo>();
            foreach (Recipe recipe in db.ListAll())
            {
                if (ratings.TryGetValue(recipe.Info.Id, out AccountRecipeRate? rate))
                {
                    if (rate.IsFavorite) 
                        favorites.Add(recipe.Info);
                }
            }
            return favorites.ToImmutableList();
        }

        public ImmutableList<(RecipeInfo, uint)> GetWeeklyList()
        {
            List<(RecipeInfo, uint)> weekly = new List<(RecipeInfo, uint)>();
            foreach (Recipe recipe in db.ListAll())
            {
                if (this.weekly.TryGetValue(recipe.Info.Id, out uint personAmmount))
                {
                    weekly.Add((recipe.Info, personAmmount));
                }
            }
            return weekly.ToImmutableList();
        }

        
        public AccountRecipeRate GetRate(RecipeInfo info)
        {
            AccountRecipeRate rate = null;
            if (!ratings.TryGetValue(info.Id, out rate))
            {
                rate = new AccountRecipeRate();
                ratings.Add(info.Id, rate);
            }
            return rate;
        }

        public void AddToFavorites(RecipeInfo info)
        {
            AccountRecipeRate rate = GetRate(info);
            ratings[info.Id] = new AccountRecipeRate(true, rate.Rate);
        }


        public bool AddToWeeklyList(RecipeInfo info, uint persAmount)
        {
            if (weekly.ContainsKey(info.Id))
                return false;

            weekly[info.Id] = persAmount;

            return true;
        }

        public void RemoveFromFavorites(RecipeInfo info)
        {
            AccountRecipeRate rate = GetRate(info);
            ratings[info.Id] = new AccountRecipeRate(false, rate.Rate);
        }

        public void SetReviewScore(RecipeInfo info, uint score)
        {
            AccountRecipeRate rate = GetRate(info);
            ratings[info.Id] = new AccountRecipeRate(rate.IsFavorite, score);
        }
    }
}
