using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using PARR.Core.Common.Interfaces;
using PARR.Domain.Settings;
using PARR.EsppApi;
using PARR.EsppApi.Models;
using PARR.EsppApi.Models.Query;
using PARR.EsppOrderLoader.Services;
using PARR.EsppOrderLoader.Settings;

namespace PARR.EsppOrderLoader
{
    internal class EsppOrderLoader : IEsppOrderLoader
    {
        private readonly WorkerSettings settings;
        private readonly ILogger<EsppOrderLoader> logger;
        private readonly IEsppApiService esppApiService;
        private readonly SettingsFromDb settingsFromDb;
        private readonly IServiceProvider serviceProvider;
        private readonly IIntervalService intervalService;

        public EsppOrderLoader(
            WorkerSettings settings,
            ILogger<EsppOrderLoader> logger,
            IEsppApiService esppApiService,
            SettingsFromDb settingsFromDb,
            IServiceProvider serviceProvider,
            IIntervalService intervalService
            )
        {
            this.settings = settings;
            this.logger = logger;
            this.esppApiService = esppApiService;
            this.settingsFromDb = settingsFromDb;
            this.serviceProvider = serviceProvider;
            this.intervalService = intervalService;
        }


        public async Task StartAsync()
        {
            logger.LogInformation("Запуск сервиса загрузки нарядов из ЕСПП.");

            try
            {
                await intervalService.IntervalInitAsync(DownloadOrdersAsync, settings.RepeatEvery);
                logger.LogDebug("Сервис загрузки нарядов из ЕСПП успешно запущен с интервалом {RepeatEvery}", settings.RepeatEvery);
            }
            catch (Exception ex)
            {
                logger.LogError(ex, "Ошибка при инициализации интервального сервиса загрузки нарядов из ЕСПП");
                throw;
            }
        }


        //Получаю список нарядов из еспп
        //проверяю есть ли наряд в бд
        //если нет, ищу шаблон в бд, затем сохраняю наряд в бд с привязанным шаблоном (если шаблон не нашел, тоже сохраняю)

        private async Task DownloadOrdersAsync()
        {
            logger.LogDebug("Начинаю процесс загрузки нарядов из ЕСПП");

            try
            {
                var esppObjs = await GetOrdersAsync();

                if (esppObjs == null || !esppObjs.Any())
                {
                    return;
                }

                foreach (var item in esppObjs)
                {
                    using (var scope = serviceProvider.CreateScope())
                    {
                        var orderItemService = scope.ServiceProvider.GetService<IOrderItemService>();
                        if (orderItemService == null)
                            throw new Exception("Не смог получить сервис IOrderItemService, scope.ServiceProvider.GetService<IOrderItemService>()");

                        try
                        {
                            logger.LogDebug("Обработка наряда {OrderNumber}", item.Number);
                            await orderItemService.WriteOrderAsync(item);
                        }
                        catch (Exception ex)
                        {
                            logger.LogError(
                                ex,
                                "Ошибка при обработке наряда {OrderNumber} из ЕСПП",
                                item?.Number ?? "неизвестно");
                        }
                    }
                }

                logger.LogDebug("Завершена обработка нарядов из ЕСПП");
            }
            catch (Exception ex)
            {
                logger.LogError(ex, "Критическая ошибка при загрузке нарядов из ЕСПП");
                throw;
            }
        }


        private async Task<IEnumerable<EsppOrder>?> GetOrdersAsync()
        {
            logger.LogDebug("Выполняю поиск нарядов в ЕСПП");

            try
            {
                var searchQuery = new FindOrdersQuery
                {
                    DescriptionContains = settingsFromDb.TemplatePrefixWithoutVariable,
                    GenerateDateStart = DateTimeOffset.UtcNow.DateTime.Add(-settingsFromDb.OrderSearchDeltaDate),
                    GenerateDateEnd = DateTimeOffset.UtcNow.DateTime
                };

                var downloadResult = await esppApiService.FindOrdersAsync(searchQuery);

                logger.LogDebug("Результат запроса к ЕСПП: IsSuccess={IsSuccess}, Data={Data}",
                    downloadResult.IsSuccess,
                    downloadResult.Data?.Count() ?? 0);

                if (!downloadResult.IsSuccess)
                {
                    logger.LogError(
                        downloadResult.Exception,
                        "Ошибка загрузки списка нарядов из ЕСПП. Ошибка: {ErrorMessage}",
                        downloadResult.Exception?.Message);
                    return null;
                }

                var data = downloadResult.Data;
                var count = data?.Count() ?? 0;

                if (data != null && count > 0)
                {
                    logger.LogInformation("Успешно получено нарядов из ЕСПП: {Count}", count);
                }
                else
                {
                    logger.LogDebug("Успешно выполнен запрос к ЕСПП, но наряды отсутствуют. Количество: {Count}", count);
                }

                return data;
            }
            catch (Exception ex)
            {
                logger.LogError(ex, "Критическая ошибка при выполнении запроса на получение нарядов из ЕСПП");
                return null;
            }
        }
    }
}