using System.Collections.Generic;
using System.Threading;
using Cysharp.Threading.Tasks;
using Darkmatter.Core.Contracts.Features.DrawingCatalog;
using Darkmatter.Core.Contracts.Features.Progression;
using Darkmatter.Core.Contracts.Services.Assets;
using Darkmatter.Core.Data.Static.Features.DrawingTemplate;
using UnityEngine;

namespace Darkmatter.Features.DrawingTemplates.Systems
{
    public sealed class AddressableDrawingTemplateCatalog : IDrawingTemplateCatalog
    {
        private const string DrawingLabel = "drawing";

        private readonly IAssetProviderService _assets;
        private readonly IProgressionSystem _progression;

        private readonly List<string> _allIds = new();
        private readonly Dictionary<string, DrawingTemplateSO> _byId = new();
        private bool _initialized;

        public IReadOnlyList<string> AllTemplateIds => _allIds;

        public AddressableDrawingTemplateCatalog(
            IAssetProviderService assets,
            IProgressionSystem progression)
        {
            _assets = assets;
            _progression = progression;
        }

        public async UniTask FetchAsync()
        {
            if (_initialized) return;

            var templates = await _assets.LoadAssetsAsync<DrawingTemplateSO>(
                key: DrawingLabel,
                progress: null,
                cancellationToken: CancellationToken.None);

            _allIds.Clear();
            _byId.Clear();
            foreach (var t in templates)
            {
                if (t == null || string.IsNullOrEmpty(t.Id)) continue;
                _allIds.Add(t.Id);
                _byId[t.Id] = t;
            }

            _allIds.Sort();
            _initialized = true;
        }

        public UniTask<Sprite> GetThumbnailAsync(string id)
        {
            if (!_byId.TryGetValue(id, out var t))
                throw new KeyNotFoundException($"Template '{id}' not in catalog. Did InitializeAsync run?");
            return UniTask.FromResult(t.DefaultThumbnail);
        }

        public UniTask<IDrawingTemplate> LoadAsync(string id)
        {
            if (_byId.TryGetValue(id, out var t))
                return UniTask.FromResult<IDrawingTemplate>(t);

            return LoadIndividualAsync(id);
        }

        private async UniTask<IDrawingTemplate> LoadIndividualAsync(string id)
        {
            var t = await _assets.LoadAssetAsync<DrawingTemplateSO>(
                id, progress: null, cancellationToken: CancellationToken.None);
            if (t == null)
                throw new KeyNotFoundException($"No drawing template at address '{id}'.");
            _byId[id] = t;
            if (!_allIds.Contains(id))
            {
                _allIds.Add(id);
                _allIds.Sort();
            }

            return t;
        }

        public void ReleaseAll()
        {
            if (!_initialized) return;
            _assets.UnloadAsset(DrawingLabel);
            _byId.Clear();
            _allIds.Clear();
            _initialized = false;
        }

        public string GetNextTemplate(string currentId)
        {
            if (_allIds.Count == 0) return null;

            int startIdx = currentId != null ? _allIds.IndexOf(currentId) : -1;

            for (int i = 1; i <= _allIds.Count; i++)
            {
                var idx = (startIdx + i) % _allIds.Count;
                var candidate = _allIds[idx];
                if (!_progression.IsCompleted(candidate))
                    return candidate;
            }

            return _allIds[(startIdx + 1) % _allIds.Count];
        }
    }
}