using AssortValidator.Common.Helpers;
using AssortValidator.Common.Helpers.Models;
using AssortValidator.Common.Models;

namespace AssortUpdater
{
    public static class QuestAssortGenerator
    {
        public static QuestAssorts CreateQuestAssorts(Trader trader, IEnumerable<QuestAssortUnlock> questAssortData, List<FlatAssort> flatAssorts)
        {
            var result = new QuestAssorts();
            int count = 1;
            foreach (var questAssortUnlock in questAssortData)
            {
                // find assort by item tpl and level
                IEnumerable<FlatAssort> associatedAssort = flatAssorts.Where(x => x.ItemId == questAssortUnlock.AssortItems[0]._tpl 
                                                                                && x.Level == questAssortUnlock.LoyaltyLevel);

                // no assort found
                if (associatedAssort?.Any() != true)
                {
                    // Add a filler item
                    result.success.Add($"MISSING{count}", questAssortUnlock.QuestId);
                    count++;
                    continue;
                }

                // One match found, woo yeah
                if (associatedAssort.Count() == 1)
                {
                    result.success.Add(associatedAssort.Single().AssortId, questAssortUnlock.QuestId);
                    continue;
                }

                // multiple found, use hand-made data from QuestAssortMappingHelper
                if (associatedAssort.Count() > 1)
                {
                    var matchingAssort = GetMatchingAssortUsingManualMapping(trader, associatedAssort, questAssortUnlock);
                    if (matchingAssort.Count == 1)
                    {
                        result.success.Add(matchingAssort.Single().AssortId, questAssortUnlock.QuestId);
                        continue;
                    }

                    if (matchingAssort.Count == 0)
                    {
                        result.success.Add($"none found {count}", questAssortUnlock.QuestId);
                        count++;
                        continue;
                    }

                    result.success.Add($"too many {count}", questAssortUnlock.QuestId);
                    count++;
                }
            }

            return result;
        }

        private static List<FlatAssort> GetMatchingAssortUsingManualMapping(Trader trader, IEnumerable<FlatAssort> possibleAssorts, QuestAssortUnlock questToFindAssortFor)
        {
            var assorts = new List<FlatAssort>();

            // Get manually made mappings to help us find the assort we want
            var manualAssortMappings = QuestAssortMappingHelper.GetQuestAssortMappingDetails(questToFindAssortFor.QuestId);
            manualAssortMappings = manualAssortMappings.Where(x => x.Trader == trader
                                                           && x.ItemTplId == questToFindAssortFor.AssortTemplateId
                                                           && x.Level == questToFindAssortFor.LoyaltyLevel).ToList();

            // there may be multiple mappings for a quest, try and filter it down by subitem count
            QuestAssortMapping singleMapping;
            if (manualAssortMappings.Count != 1)
            {
                singleMapping = manualAssortMappings.Single(x => (x.SubItemCount ?? 0) == questToFindAssortFor.AssortItems.Count - 1); // remove base item from count
            }
            else
            {
                singleMapping = manualAssortMappings[0];
            }

            // Find matching assort
            assorts = possibleAssorts.Where(x => x.IsMoney == singleMapping.IsMoneyBarter
                                                         && trader == singleMapping.Trader
                                                         && x.Level == singleMapping.Level
                                                         && x.RawItem._tpl == singleMapping.ItemTplId).ToList();

            // Filter assort on subitem count
            if (assorts.Count > 1)
            {
                assorts = assorts.Where(x => x.SubItems.Count == singleMapping.SubItemCount).ToList();
            }

            // Hopefully just one
            return assorts;
        }


    }
}