using Azure.Cosmos;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using System;
using System.Collections.Concurrent;

namespace TEAMModelOS.SDK.DI
{
    public class AzureCosmosFactory
    {
        private readonly IServiceProvider _services;
        private readonly IOptionsMonitor<AzureCosmosFactoryOptions> _optionsMonitor;
        private readonly ILogger _logger;
        //private Option _option;
        private ConcurrentDictionary<string, CosmosClient> CosmosClients { get; } = new ConcurrentDictionary<string, CosmosClient>();
        
        //   private CosmosDatabase database { get; set; }
        
        public AzureCosmosFactory(IServiceProvider services, IOptionsMonitor<AzureCosmosFactoryOptions> optionsMonitor, ILogger<AzureCosmosFactory> logger)
        {
            if (services == null) throw new ArgumentNullException(nameof(services));
            if (optionsMonitor == null) throw new ArgumentNullException(nameof(optionsMonitor));

            _services = services;
            _optionsMonitor = optionsMonitor;
            _logger = logger;  
        }

        /// <summary>
        /// 取得CosmosClient，支持安全執行緒
        /// </summary>
        /// <param name="name"></param>
        /// <param name="region">可以使用Regions.{區域}設置，指定此屬性後，SDK會首選該區域來執行操作。此外，SDK會自動選擇後備的地理複製區域以實現高可用性。如果未指定此屬性，則SDK會將寫區域用作所有操作的首選區域</param>
        /// <returns></returns>
        public CosmosClient GetCosmosClient(string region = null, string name = "Default")
        {
            try
            {
                //CosmosClientOptions 的 SerializerOptions = new CosmosSerializationOptions() { PropertyNamingPolicy = CosmosPropertyNamingPolicy.CamelCase } 
                //需等待官方修正
                var cm = CosmosClients.GetOrAdd(name, x => new CosmosClient(_optionsMonitor.Get(name).CosmosConnectionString, new CosmosClientOptions() {  ApplicationRegion = region }));
                return cm;
            }
            catch (Exception e)
            {
                _logger?.LogWarning(e, e.Message);
                return null;
            }
        }
    }
}
