namespace TeleWave.Application.Common.Models;

public class Result
{
    public bool IsSuccess { get; }
    public Error Error { get; }

    protected Result(bool isSuccess, Error error)
    {
        if (isSuccess && error != Error.None)
            throw new InvalidOperationException("Успешный результат не может содержать ошибку.");
        if (!isSuccess && error == Error.None)
            throw new InvalidOperationException("Неуспешный результат обязан содержать ошибку.");

        IsSuccess = isSuccess;
        Error = error;
    }

    public static Result Success() => new(true, Error.None);

    public static Result<T> Success<T>(T value) => new(value, true, Error.None);

    public static Result Failure(Error error) => new(false, error);

    public static Result<T> Failure<T>(Error error) => new(default, false, error);
}

public class Result<T> : Result
{
    private readonly T? _value;

    internal Result(T? value, bool isSuccess, Error error)
        : base(isSuccess, error) => _value = value;

    public T Value =>
        IsSuccess
            ? _value!
            : throw new InvalidOperationException(
                "Нельзя получить значение неуспешного результата."
            );

    public static implicit operator Result<T>(T value) => Success(value);
}
