using Npgsql;

namespace ComputerSalesApp.Services;

internal static class ErrorHandler
{
    public static void Show(string title, string userAction, Exception ex)
    {
        MessageBox.Show(
            BuildMessage(userAction, ex),
            title,
            MessageBoxButtons.OK,
            MessageBoxIcon.Error);
    }

    public static void ShowInfo(string title, string message)
    {
        MessageBox.Show(message, title, MessageBoxButtons.OK, MessageBoxIcon.Information);
    }

    public static bool Confirm(string message)
    {
        return MessageBox.Show(message, "Подтверждение", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes;
    }

    private static string BuildMessage(string userAction, Exception ex)
    {
        Exception baseException = ex.GetBaseException();
        string friendly = GetFriendlyText(baseException);

        return $"{userAction}\n\n{friendly}\n\nТехнические подробности:\n{baseException.Message}";
    }

    private static string GetFriendlyText(Exception ex)
    {
        if (ex is UserFriendlyException)
        {
            return ex.Message;
        }

        if (ex is FileNotFoundException || ex is FileLoadException)
        {
            return "Не найдена или не загрузилась одна из библиотек приложения. " +
                   "Откройте проект в Visual Studio, выполните Restore NuGet Packages и Rebuild Solution.";
        }

        if (ex is TimeoutException)
        {
            return "Превышено время ожидания операции. Проверьте интернет, доступность сервера PostgreSQL и попробуйте снова.";
        }

        if (ex is PostgresException pg)
        {
            return pg.SqlState switch
            {
                "23505" => "Такая запись уже существует. Проверьте поля, которые должны быть уникальными.",
                "23503" => "Нельзя выполнить операцию, потому что запись связана с другими таблицами. Например, нельзя удалить товар, который уже есть в заказах или остатках.",
                "23502" => "Не заполнено обязательное поле.",
                "23514" => "Нарушено проверочное ограничение БД. Проверьте количество, цену, вместимость, дату рождения или статус.",
                "22P02" => "Некорректный формат значения. Проверьте введённые числа и даты.",
                "42883" => "В базе данных не найдена нужная функция. Проверьте, что выполнен SQL-скрипт создания функции авторизации.",
                "42P01" => "В базе данных не найдена нужная таблица или представление. Проверьте, что выполнен SQL-скрипт создания таблиц.",
                "42703" => "В базе данных не найден нужный столбец. Проверьте, что структура БД соответствует проекту.",
                "3F000" => "Не найдена схема ryzhov_ka. Проверьте search_path и подключение под нужным пользователем.",
                "28P01" => "Неверный логин или пароль для подключения к PostgreSQL.",
                "42501" => "Недостаточно прав для выполнения операции в базе данных.",
                _ => "PostgreSQL вернул ошибку при выполнении операции."
            };
        }

        if (ex is NpgsqlException)
        {
            return "Не удалось выполнить запрос к PostgreSQL. Проверьте подключение к серверу, строку подключения и наличие объектов БД.";
        }

        if (ex is InvalidOperationException)
        {
            return "Операцию нельзя выполнить в текущем состоянии приложения. Проверьте выбранную запись и повторите попытку.";
        }

        return "Произошла непредвиденная ошибка приложения.";
    }
}
