using Microsoft.Extensions.Configuration;
using DD.Persistence.Client.Clients.Interfaces;
using DD.Persistence.Client.Clients;
using DD.Persistence.Client.Helpers;
using Refit;
using DD.Persistence.Factories;
using DD.Persistence.Client.Clients.Interfaces.Refit;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.DependencyInjection;
using System.Text.Json;

namespace DD.Persistence.Client
{
	/// <summary>
	/// Фабрика клиентов для доступа к Persistence - сервису
	/// </summary>
	public class PersistenceClientFactory
	{
		private static readonly JsonSerializerOptions JsonSerializerOptions = new()
		{
			PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
			PropertyNameCaseInsensitive = true
		};
		private static readonly RefitSettings RefitSettings = new(new SystemTextJsonContentSerializer(JsonSerializerOptions));
		private readonly IServiceProvider provider;
		private HttpClient httpClient;
		public PersistenceClientFactory(IHttpClientFactory httpClientFactory, IServiceProvider provider, IConfiguration configuration)
		{
			this.provider = provider;

			httpClient = httpClientFactory.CreateClient();

			httpClient.Authorize(configuration);
		}

		public PersistenceClientFactory(IHttpClientFactory httpClientFactory, IAuthTokenFactory authTokenFactory, IServiceProvider provider, IConfiguration configuration)
		{
			this.provider = provider;

			httpClient = httpClientFactory.CreateClient();

			var token = authTokenFactory.GetToken();
			httpClient.Authorize(token);
		}

		/// <summary>
		/// Получить клиент для работы с уставками
		/// </summary>
		/// <returns></returns>
		public ISetpointClient GetSetpointClient()
		{
			var logger = provider.GetRequiredService<ILogger<SetpointClient>>();

			var restClient = RestService.For<IRefitSetpointClient>(httpClient, RefitSettings);
			var client = new SetpointClient(restClient, logger);

			return client;
		}

		/// <summary>
		/// Получить клиент для работы с технологическими сообщениями
		/// </summary>
		/// <returns></returns>
		public ITechMessagesClient GetTechMessagesClient()
		{
			var logger = provider.GetRequiredService<ILogger<TechMessagesClient>>();

			var restClient = RestService.For<IRefitTechMessagesClient>(httpClient, RefitSettings);
			var client = new TechMessagesClient(restClient, logger);

			return client;
		}

		/// <summary>
		/// Получить клиент для работы с временными данными
		/// </summary>
		/// <typeparam name="TDto"></typeparam>
		/// <returns></returns>
		public ITimeSeriesClient<TDto> GetTimeSeriesClient<TDto>()
			where TDto : class, new()
		{
			var logger = provider.GetRequiredService<ILogger<TimeSeriesClient<TDto>>>();

			var restClient = RestService.For<IRefitTimeSeriesClient<TDto>>(httpClient, RefitSettings);
			var client = new TimeSeriesClient<TDto>(restClient, logger);

			return client;
		}

		/// <summary>
		/// Получить клиент для работы с данными с отметкой времени
		/// </summary>
		/// <returns></returns>
		public ITimestampedSetClient GetTimestampedSetClient()
		{
			var logger = provider.GetRequiredService<ILogger<TimestampedSetClient>>();

			var restClient = RestService.For<IRefitTimestampedSetClient>(httpClient, RefitSettings);
			var client = new TimestampedSetClient(restClient, logger);

			return client;
		}

		/// <summary>
		/// Получить клиент для работы с записями ChangeLog
		/// </summary>
		/// <returns></returns>
		public IChangeLogClient GetChangeLogClient()
		{
			var logger = provider.GetRequiredService<ILogger<ChangeLogClient>>();

			var restClient = RestService.For<IRefitChangeLogClient>(httpClient, RefitSettings);
			var client = new ChangeLogClient(restClient, logger);

			return client;
		}

		/// <summary>
		/// Получить клиент для работы c параметрами Wits
		/// </summary>
		/// <returns></returns>
		public IWitsDataClient GetWitsDataClient()
		{
			var logger = provider.GetRequiredService<ILogger<WitsDataClient>>();

			var restClient = RestService.For<IRefitWitsDataClient>(httpClient, RefitSettings);
			var client = new WitsDataClient(restClient, logger);

			return client;
		}

		/// <summary>
		/// Получить клиент для работы c системами
		/// </summary>
		/// <returns></returns>
		public IDataSourceSystemClient GetDataSourceSystemClient()
		{
			var logger = provider.GetRequiredService<ILogger<DataSourceSystemClient>>();

			var restClient = RestService.For<IRefitDataSourceSystemClient>(httpClient, RefitSettings);
			var client = new DataSourceSystemClient(restClient, logger);

			return client;
		}
	}
}