using MMoneyCoderSharp.Data;

namespace MBN_STOCK_WEBVIEW.Infrastructure;

public class DatabaseInfrastructureException : Exception
{
    public DatabaseInfrastructureException(string message)
        : base(message)
    {
    }
}

public sealed class DatabaseConfigurationException : DatabaseInfrastructureException
{
    public DatabaseConfigurationException(string message)
        : base(message)
    {
    }
}

public abstract class DatabaseOperationException : DatabaseInfrastructureException
{
    protected DatabaseOperationException(
        DataSourceKind source,
        string message,
        bool isTransient,
        int? providerErrorCode = null)
        : base(message)
    {
        DataSource = source;
        IsTransient = isTransient;
        ProviderErrorCode = providerErrorCode;
    }

    public DataSourceKind DataSource { get; }

    public bool IsTransient { get; }

    public int? ProviderErrorCode { get; }
}

public sealed class DatabaseNotConfiguredException : DatabaseOperationException
{
    public DatabaseNotConfiguredException(DataSourceKind source, IReadOnlyList<string> invalidSettings)
        : base(
            source,
            $"{source} 데이터베이스 연결 정보가 설정되지 않았습니다. " +
            $"확인할 항목: {string.Join(", ", invalidSettings)}.",
            isTransient: false)
    {
        InvalidSettings = invalidSettings.ToArray();
    }

    public IReadOnlyList<string> InvalidSettings { get; }
}

public sealed class DatabaseQueryException : DatabaseOperationException
{
    public DatabaseQueryException(
        DataSourceKind source,
        bool isTransient,
        int? providerErrorCode = null)
        : base(
            source,
            "데이터베이스 요청을 처리할 수 없습니다. 연결 설정과 네트워크 상태를 확인하세요.",
            isTransient,
            providerErrorCode)
    {
    }
}

public sealed class DatabaseQueryTimeoutException : DatabaseOperationException
{
    public DatabaseQueryTimeoutException(DataSourceKind source)
        : base(
            source,
            "데이터베이스 응답 시간이 초과되었습니다. 잠시 후 다시 시도하세요.",
            isTransient: true)
    {
    }
}
