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

namespace RealEstateTransactions.Repositories.Implementations
{
    public class ApartmentRepository : IApartmentRepository
    {
        private readonly IConnectionString _connectionString;

        private readonly ILogger<ApartmentRepository> _logger;

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

        public void CreateApartment(Apartment apartment)
        {
            _logger.LogInformation("Добавление объекта");
            _logger.LogDebug("Объект: {json}", JsonConvert.SerializeObject(apartment));
            try
            {
                using var connection = new NpgsqlConnection(_connectionString.ConnectionString);
                var insertQuery = @"
INSERT INTO Apartment (Agency_ID, Form_factor_ID, Area, Price_per_SM, Base_price, Desired_price)
VALUES (@Agency_ID, @Form_factor_ID, @Area, @Price_per_SM, @Base_price, @Desired_price)";
                connection.Execute(insertQuery, apartment);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Ошибка при добавлении объекта");
                throw;
            }
        }
        public void UpdateApartment(Apartment apartment)
        {
            _logger.LogInformation("Редактирование объекта");
            _logger.LogDebug("Объект: {json}", JsonConvert.SerializeObject(apartment));
            try
            {
                using var connection = new NpgsqlConnection(_connectionString.ConnectionString);
                var updateQuery = @"
UPDATE Apartment
SET
    Agency_ID = @Agency_ID,
    Form_Factor_ID = @Form_factor_ID,
    Area = @Area,
    Price_per_SM = @Price_per_SM,
    Base_price = @Base_price,
    Desired_price = @Desired_price
WHERE Id = @Id";
                connection.Execute(updateQuery, apartment);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Ошибка при редактировании оьъекта");
                throw;
            }
        }

        public Apartment ReadApartment(int id)
        {
            _logger.LogInformation("Получение объекта по идентификатору");
            _logger.LogDebug("Объект: {Id}", id);
            try
            {
                using var connection = new NpgsqlConnection(_connectionString.ConnectionString);
                var selectQuery = @"
SELECT *
FROM Apartment
WHERE ID = @id";
                var apartment = connection.QueryFirst<Apartment>(selectQuery, new { id });
                _logger.LogDebug("Найден объект: {json}", JsonConvert.SerializeObject(apartment));
                return apartment;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Ошибка при поиске объекта");
                throw;
            }
        }

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

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

    }
}