using Dapper;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Npgsql;
using ProjectItCompany.Entities;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ProjectItCompany.Repositories.Implementations;

public class ExecutorRepository : IExecutorRepository
{
    private readonly IConnectionString _connectionString;
    private readonly ILogger<ExecutorRepository> _logger;

    public ExecutorRepository(IConnectionString connectionString, ILogger<ExecutorRepository> logger)
    {
        _connectionString = connectionString;
        _logger = logger;
    }
    public void CreateExecutor(Executor executor)
    {
        _logger.LogInformation("Добавление объекта");
        _logger.LogDebug("Объект: {json}", JsonConvert.SerializeObject(executor));
        try
        {
            using var connection = new NpgsqlConnection(_connectionString.ConnectionString);
            var queryInsert = @"INSERT INTO executor (FullName, DateOfBirth, HourlyRate, JobTitles) 
                                VALUES (@FullName, @DateOfBirth, @HourlyRate, @JobTitles)";
            connection.Execute(queryInsert, executor);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Ошибка при добавлении объекта");
            throw;
        }
    }

    public void UpdateExecutor(Executor executor)
    {
        _logger.LogInformation("Редактирование объекта");
        _logger.LogDebug("Объект: {json}",
        JsonConvert.SerializeObject(executor));
        try
        {
            using var connection = new NpgsqlConnection(_connectionString.ConnectionString);
            var queryUpdate = @"UPDATE executor SET
                                    FullName=@FullName,
                                    DateOfBirth=@DateOfBirth,
                                    HourlyRate=@HourlyRate,
                                    JobTitles = @JobTitles
                                    WHERE ID=@id";
            connection.Execute(queryUpdate, executor);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Ошибка при редактировании объекта");
            throw;
        }
    }

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

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

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