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

namespace RealEstateTransactions.Repositories.Implementations
{
    public class DealRepository : IDealRepository
    {
        private readonly IConnectionString _connectionString;

        private readonly ILogger<DealRepository> _logger;

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

        public void CreateDeal(Deal deal)
        {
            _logger.LogInformation("Добавление объекта");
            _logger.LogDebug("Объект: {json}", JsonConvert.SerializeObject(deal));
            try
            {
                using var connection = new NpgsqlConnection(_connectionString.ConnectionString);
                connection.Open();
                using var transaction = connection.BeginTransaction();
                var insertQuery = @"
INSERT INTO Deal (Apartment_ID, Buyer_ID, Deal_price, Deal_date)
VALUES (@Apartment_ID, @Buyer_ID, @Deal_price, @Deal_date);
SELECT MAX(Id) FROM Deal";
                var dealId = connection.QueryFirst<int>(insertQuery, deal, transaction);

                var subInsertQuery = @"
INSERT INTO Services_Deal (Services_ID, Deal_ID, Execution_time)
VALUES (@Services_ID, @Deal_ID, @Execution_time)";
                foreach (var elem in deal.DealServices)
                {
                    connection.Execute(subInsertQuery, new { elem.Services_ID, 
                        Deal_ID = dealId, elem.Execution_time }, transaction);
                }

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

        public void DeleteDeal(int id)
        {
            _logger.LogInformation("Удаление объекта");
            _logger.LogDebug("Объект: {Id}", id);
            try
            {
                using var connection = new NpgsqlConnection(_connectionString.ConnectionString);
                var deleteQuery = @"
DELETE FROM Deal
WHERE Id = @id";
                connection.Execute(deleteQuery, new { id });
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Ошибка при удалении объекта");
                throw;
            }
        }

        public IEnumerable<Deal> ReadDeals(DateTime? dateForm = null, DateTime? dateTo = null,
            int? servicesID = null, int? dealID = null)
        {
            _logger.LogInformation("Получение всех объектов");
            try
            {
                using var connection = new NpgsqlConnection(_connectionString.ConnectionString);
                var selectQuery = @"SELECT * FROM Deal";
                var deals = connection.Query<Deal>(selectQuery);
                _logger.LogDebug("Полученные объекты: {json}", JsonConvert.SerializeObject(deals));
                return deals;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Ошибка при чтении объектов");
                throw;
            }
        }
    }
}