using System.Data.SqlClient;
using System.Text.Json;
using Dapper;
using Microsoft.Extensions.Logging;
using Npgsql;
using ProjectGSM.Entities;

namespace ProjectGSM.Repositories.Implementations;

public class AdvocateRepository : IAdvocateRepository
{
    private readonly IConnectionString _connectionString;
    private readonly ILogger<AdvocateRepository> _logger;

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

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

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

    public void CreateAdvocate(Advocate advocate)
    {
        _logger.LogInformation("Добавление объекта");
        _logger.LogDebug("Объект: {json}",
            JsonSerializer.Serialize(advocate));
        try
        {
            using var connection = new
                NpgsqlConnection(_connectionString.ConnectionString);
            var queryInsert = @"
INSERT INTO advocates (name, sex, dateofbirth, experience, completed_tasks, rating, email, phonenumber, address, licensetype, createdat)
VALUES (@Name, @Sex, @DateOfBirth, @Experience, @CompletedTasks, @Rating, @Email, @PhoneNumber, @Address, @LicenseType, @CreatedAt)";
            connection.Execute(queryInsert, advocate);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Ошибка при добавлении объекта");
            throw;
        }
    }

    public void UpdateAdvocate(Advocate advocate)
    {
        _logger.LogInformation("Обновление объекта");
        _logger.LogDebug("Объект: {json}",
            JsonSerializer.Serialize(advocate));
        try
        {
            using var connection = new
                NpgsqlConnection(_connectionString.ConnectionString);
            var queryUpdate = @"UPDATE advocates
                            SET id = @Id,
                                name = @Name,
                                sex = @Sex,
                                dateofbirth = @DateOfBirth,
                                experience = @Experience,
                                completed_tasks = @CompletedTasks,
                                rating = @Rating,
                                email = @Email,
                                phonenumber = @PhoneNumber,
                                address = @Address,
                                licensetype = @LicenseType,
                                createdat = @CreatedAt
                            WHERE id = @Id;";
            connection.Execute(queryUpdate, advocate);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Ошибка при обновлении объекта");
            throw;
        }
    }

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