using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace MW.WorkFlow
{
    public class WorkflowContext
    {
        private const string RouteKeyPrefix = "Route:";
        private readonly ConcurrentDictionary<string, object> _data = new ConcurrentDictionary<string, object>();

        public object this[string key]
        {
            get
            {
                if (_data.TryGetValue(key, out var value))
                {
                    return value;
                }
                throw new KeyNotFoundException($"Key '{key}' not found in WorkflowContext.");
            }
            set
            {
                _data[key] = value;
            }
        }
        public void SetData<T>(string key, T value)
        {
            _data[key] = value;
        }
        public T GetData<T>(string key)
        {
            if (_data.TryGetValue(key, out var value) && value is T typedValue)
            {
                return typedValue;
            }
            throw new KeyNotFoundException($"Key '{key}' not found or of incorrect type.");
        }
        public bool TryGetData<T>(string key, out T value)
        {
            if (_data.TryGetValue(key, out var obj) && obj is T typedValue)
            {
                value = typedValue;
                return true;
            }
            value = default;
            return false;
        }
        public bool ContainsKey(string key)
        {
            return _data.ContainsKey(key);
        }

        public void SetRoute<T>(string routeKey, T value)
        {
            SetData(BuildRouteKey(routeKey), value);
        }

        public T GetRoute<T>(string routeKey)
        {
            return GetData<T>(BuildRouteKey(routeKey));
        }

        public bool TryGetRoute<T>(string routeKey, out T value)
        {
            return TryGetData(BuildRouteKey(routeKey), out value);
        }

        public bool ContainsRoute(string routeKey)
        {
            return ContainsKey(BuildRouteKey(routeKey));
        }

        public void Clear() { _data.Clear(); }

        public Dictionary<string, object> ToDictionary()
        {
            return new Dictionary<string, object>(_data);
        }

        private static string BuildRouteKey(string routeKey)
        {
            if (string.IsNullOrWhiteSpace(routeKey))
            {
                throw new ArgumentNullException(nameof(routeKey));
            }

            return RouteKeyPrefix + routeKey;
        }

    }
}
