using Dapper;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Npgsql;
using ProjectShoeShop.Entities;

namespace ProjectShoeShop.Repositories.Implementations;

public class SupplyRepository : ISupplyRepository
{
    private readonly IConnectionString _connectionString;
    private readonly ILogger<SupplyRepository> _logger;

    public SupplyRepository(IConnectionString connectionString, ILogger<SupplyRepository> logger)
    {
        _connectionString = connectionString;
        _logger = logger;
    }

    public void CreateSupply(Supply supply)
    {
        _logger.LogInformation("Добавление объекта");
        _logger.LogDebug("Объект: {json}",
        JsonConvert.SerializeObject(supply));
        try
        {
            using var connection = new
            NpgsqlConnection(_connectionString.ConnectionString);
            connection.Open();
            using var transaction = connection.BeginTransaction();
            var queryInsert = @"
                INSERT INTO Supply (SupplyType, DateOfReceipt)
                VALUES (@SupplyType, @DateOfReceipt);
                SELECT MAX(Id) FROM Supply";
            var supplyId =
            connection.QueryFirst<int>(queryInsert, supply, transaction);
            var querySubInsert = @"
                INSERT INTO SupplyShoes (SupplyId, ShoesId, NumberOfPairs, Size)
                VALUES (@SupplyId, @ShoesId, @NumberOfPairs, @Size)";
            foreach (var elem in supply.SupplyShoes)
            {
                connection.Execute(querySubInsert, new
                {
                    supplyId,
                    elem.ShoesId,
                    elem.NumberOfPairs,
                    elem.Size
                }, transaction);
            }
            transaction.Commit();
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Ошибка при добавлении объекта");
            throw;
        }
    }

    public IEnumerable<Supply> ReadSupply(DateTime? dateForm = null, DateTime? dateTo = null)
    {
        _logger.LogInformation("Получение всех объектов");
        try
        {
            using var connection = new NpgsqlConnection(_connectionString.ConnectionString);
            var querySelect = @"SELECT sup.*, sups.ShoesId, sups.Size, sups.NumberOfPairs FROM Supply sup
                                INNER JOIN SupplyShoes sups on sup.Id = sups.SupplyId";
            var supplies = connection.Query<TempSupplyShoes>(querySelect);
            _logger.LogDebug("Полученные объекты: {json}",
            JsonConvert.SerializeObject(supplies));
            return supplies.GroupBy(x => x.Id, y => y, (key, value) => Supply.CreateEntity(value.First(), value.Select(z => SupplyShoes.CreateElement(0, z.ShoesId, z.Size, z.NumberOfPairs)))).ToList();
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Ошибка при чтении объектов");
            throw;
        }
    }


    public void DeleteSupply(int id)
    {
        _logger.LogInformation("Удаление объекта");
        _logger.LogDebug("Объект: {id}", id);
        try
        {
            using var connection = new NpgsqlConnection(_connectionString.ConnectionString);
            connection.Open();
            using var transaction = connection.BeginTransaction();
            var queryDeleteSub = @"
            DELETE FROM SupplyShoes
            WHERE SupplyId = @id";
            connection.Execute(queryDeleteSub, new { id }, transaction);

            var queryDelete = @"
            DELETE FROM Supply
            WHERE Id = @id";
            connection.Execute(queryDelete, new { id }, transaction);

            transaction.Commit();
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Ошибка при удалении объекта");
            throw;
        }
    }
}
