using System;
using System.Collections.Generic;
using PhoenixLib.Caching;
using PhoenixLib.Logging;
using WingsEmu.DTOs.ServerDatas;
using WingsEmu.Game.Items;
using WingsEmu.Plugins.BasicImplementations.ServerConfigs.ImportObjects;
using WingsEmu.Plugins.BasicImplementations.ServerConfigs.ImportObjects.ItemBoxes;
using WingsEmu.Plugins.BasicImplementations.ServerConfigs.Persistence;

namespace WingsEmu.Plugins.BasicImplementations.ServerConfigs;

public class ItemBoxManager : IItemBoxManager
{
    private readonly IEnumerable<ItemBoxImportFile> _itemBoxConfigurations;
    private readonly IKeyValueCache<ItemBoxDto> _itemBoxesCache;
    private readonly IEnumerable<RandomBoxImportFile> _randomBoxConfigurations;

    public ItemBoxManager(IEnumerable<ItemBoxImportFile> itemBoxConfigurations, IEnumerable<RandomBoxImportFile> randomBoxConfigurations, IKeyValueCache<ItemBoxDto> itemBoxesCache)
    {
        _itemBoxConfigurations = itemBoxConfigurations;
        _randomBoxConfigurations = randomBoxConfigurations;
        _itemBoxesCache = itemBoxesCache;
    }

    public ItemBoxDto GetItemBoxByItemVnumAndDesign(int itemVnum) => _itemBoxesCache.Get(itemVnum.ToString());

    public void Initialize()
    {
        List<ItemBoxDto> allBoxes = null;
        bool dbFirst = ParserDataPostgresReader.DbFirstEnabled;
        bool strictDbOnly = ParserDataPostgresReader.StrictDbOnlyEnabled;

        if (dbFirst)
        {
            try
            {
                allBoxes = ParserDataPostgresReader.LoadItemBoxes();
                Log.Info($"[DB_FIRST] Loaded {allBoxes.Count} item_boxes from database");
            }
            catch (Exception e)
            {
                if (strictDbOnly)
                {
                    throw new InvalidOperationException("DB_FIRST/STRICT_DB_ONLY enabled but failed to load item_boxes from database.", e);
                }

                Log.Error("[DB_FIRST] Could not load item_boxes from database", e);
            }

            if (strictDbOnly && (allBoxes == null || allBoxes.Count == 0))
            {
                throw new InvalidOperationException("DB_FIRST/STRICT_DB_ONLY enabled but no item_boxes were loaded from database.");
            }
        }

        if (allBoxes == null || allBoxes.Count == 0)
        {
            allBoxes = new List<ItemBoxDto>();
            foreach (ItemBoxImportFile file in _itemBoxConfigurations)
            {
                ItemBoxDto box = file.ToDto();
                if (box == null)
                {
                    continue;
                }

                allBoxes.Add(box);
            }

            foreach (RandomBoxImportFile file in _randomBoxConfigurations)
            {
                foreach (RandomBoxObject obj in file.Items)
                {
                    ItemBoxDto box = obj.ToDtos();
                    if (box == null)
                    {
                        continue;
                    }

                    allBoxes.Add(box);
                }
            }

            ParserDataPostgresSync.SyncItemBoxes(allBoxes);
        }

        foreach (ItemBoxDto box in allBoxes)
        {
            _itemBoxesCache.Set(box.Id.ToString(), box);
        }

        Log.Info($"[ITEMBOX_MANAGER] Loaded {allBoxes.Count} itemBoxes");
    }
}
