using AssortGenerator.Common;
using AssortGenerator.Common.Helpers;
using AssortGenerator.Common.Models;
using AssortGenerator.Models.Output;
using Common;
using System.Linq;
using System.Text.Json;

namespace CreateAssortFromFleaJsons
{
    public class Program
    {
        private static readonly List<FleaOffer> _findResults = [];

        static void Main(string[] args)
        {
            // Create input and ouput folders
            var inputPath = CreateWorkingFolders();

            // Read in all files inside input folder
            InputFileHelper.SetInputFiles(inputPath);

            // Read paths, get file and convert file contents into an object,
            // Store object inside _findResults
            var fleaFilePaths = InputFileHelper.GetInputFilePaths().ToList();
            foreach (var path in fleaFilePaths)
            {
                var json = File.ReadAllText(path);
                var findResult = JsonSerializer.Deserialize<FleaFindResult>(json);
                _findResults.AddRange(findResult.data.offers);
            }

            // Limit flea offers to just this trader
            var traderIdToProcess = "6617beeaa9cfa777ca915b7c"; // REF
            var traderSpecificFleaData = _findResults.Where(find => find.user.id == traderIdToProcess);
            var uniqueFilteredOffers = FilterUniqueOffers(traderSpecificFleaData);

            // Prep assort output file
            var assortResult = new AssortRoot()
            {
                items = new List<Item>(),
                barter_scheme = new Dictionary<string, List<List<BarterObject>>>(),
                loyal_level_items = new Dictionary<string, int>()
            };
            foreach (var fleaOffer in uniqueFilteredOffers)
            {
                // Has only one item
                var singularItem = fleaOffer.items.Count == 1;

                // First item in offer
                var firstItem = fleaOffer.items[0];

                // Add first item
                var firstItemToAdd = new Item
                {
                    _id = firstItem._id,
                    _tpl = firstItem._tpl,
                    parentId = "hideout",
                    slotId = "hideout",
                    upd = firstItem.upd
                };
                if (fleaOffer.buyRestrictionMax != null)
                {
                    firstItemToAdd.upd.BuyRestrictionMax = fleaOffer.buyRestrictionMax;
                }

                firstItemToAdd.upd.UnlimitedCount = fleaOffer.unlimitedCount;
                firstItemToAdd.upd.BuyRestrictionCurrent = 0;

                assortResult.items.Add(firstItemToAdd);

                // Add child items
                if (!singularItem)
                {
                    // Exclude first item
                    var childItems = fleaOffer.items.Except([firstItem]);
                    var locationValue = 0;
                    foreach (var childItem in childItems)
                    {
                        var itemToAdd = new Item()
                        {
                            _id = childItem._id,
                            _tpl = childItem._tpl,
                            parentId = childItem.parentId,
                            slotId = childItem.slotId,
                            upd = childItem.upd
                        };

                        if (childItem.slotId == "cartridges")
                        {
                            itemToAdd.location = locationValue;
                            locationValue++;
                        }

                        assortResult.items.Add(itemToAdd);

                        
                    }
                }

                // Add barter_scheme
                var barterItemListInner = new List<BarterObject>
                {
                    // Assumes only one item for bartering
                    new() { _tpl = fleaOffer.requirements[0]._tpl, count = fleaOffer.requirements[0].count }
                };
                var barterItemListOuter = new List<List<BarterObject>> { barterItemListInner };
                assortResult.barter_scheme.Add(firstItem._id, barterItemListOuter);

                // Add loyal_level
                assortResult.loyal_level_items.Add(firstItem._id, fleaOffer.loyaltyLevel);
            }

            JsonWriter.WriteJson(assortResult, "", Directory.GetCurrentDirectory(), "assort");
        }

        private static IEnumerable<FleaOffer> FilterUniqueOffers(IEnumerable<FleaOffer> traderSpecificFleaData)
        {
            var results = new List<FleaOffer>();
            foreach (var offer in traderSpecificFleaData)
            {
                // Is a child, add it
                if (offer.items[0].upd == null)
                {
                    results.Add(offer);
                }

                // Has upd object, base item
                // Get values to compare against
                var itemCount = offer.items.Count;
                var offerRootTpl = offer.items[0]._tpl;
                var itemsCost = offer.itemsCost;
                var requirementsCount = offer.requirements[0].count;
                var loyaltyLevel = offer.loyaltyLevel;
                var buyRestrictionMax = offer.buyRestrictionMax;

                var existingItem = results.Exists((resultOffer => resultOffer.items.Count == itemCount
                                                           && resultOffer.items[0]._tpl == offerRootTpl
                                                           && resultOffer.itemsCost == itemsCost
                                                           && resultOffer.requirements[0].count == requirementsCount
                                                           && resultOffer.loyaltyLevel == loyaltyLevel
                                                           && resultOffer.buyRestrictionMax.ToString() == buyRestrictionMax.ToString()));

                if (!existingItem)
                {
                    results.Add(offer);
                }
            }

            return results;
        }

        private static string CreateWorkingFolders()
        {
            var workingPath = Directory.GetCurrentDirectory();
            // create input folder
            var inputPath = $"{workingPath}//input";
            DiskHelpers.CreateDirIfDoesntExist(inputPath);

            // create output folder
            var outputPath = $"{workingPath}//output";
            DiskHelpers.CreateDirIfDoesntExist(outputPath);

            return inputPath;
        }
    }
}