namespace Forwarder.Models;

/// <summary>
/// Результат выполнения операции.
/// </summary>
public readonly struct Result
{
	/// <summary>
	/// Выполнена ли операция неуспешно.
	/// </summary>
	public bool IsFail { get; }

	/// <summary>
	/// Выполнена ли операция успешно.
	/// </summary>
	public bool IsSuccess => !IsFail;

	/// <summary>
	/// Ошибка.
	/// </summary>
	public string Error { get; } = string.Empty;

	/// <summary>
	/// Создает результат с ошибкой.
	/// </summary>
	/// <param name="error">Ошибка.</param>
	/// <returns>Результат.</returns>
	public static Result Fail(string error)
	{
		return new Result(error);
	}

	/// <summary>
	/// Создает успешный результат.
	/// </summary>
	public static Result Success()
	{
		return new Result();
	}

	/// <summary>
	/// Создает неуспешный результат с ошибкой.
	/// </summary>
	/// <param name="error">Ошибка.</param>
	public Result(string error)
	{
		Error = error;
		IsFail = true;
	}

	/// <summary>
	/// Создает успешный результат.
	/// </summary>
	public Result()
	{
		IsFail = false;
	}

	/// <summary>
	/// Создает неуспешный результат с ошибкой.
	/// </summary>
	/// <param name="error">Ошибка.</param>
	public static implicit operator Result(string error)
	{
		return Fail(error);
	}
}

/// <summary>
/// Результат выполнения операции с данными.
/// </summary>
/// <typeparam name="T">Тип данных.</typeparam>
public readonly struct Result<T>
{
	/// <summary>
	/// Выполнена ли операция неуспешно.
	/// </summary>
	public bool IsFail { get; }

	/// <summary>
	/// Выполнена ли операция успешно.
	/// </summary>
	public bool IsSuccess => !IsFail;

	/// <summary>
	/// Ошибка.
	/// </summary>
	public string Error { get; } = string.Empty;

	/// <summary>
	/// Создает результат с ошибкой.
	/// </summary>
	/// <param name="error">Ошибка.</param>
	/// <returns>Результат.</returns>
	public static Result<T> Fail(string error)
	{
		return new Result<T>(error);
	}

	/// <summary>
	/// Значение.
	/// </summary>
	public T Value { get; } = default!;

	/// <summary>
	/// Создает неуспешный результат с ошибкой.
	/// </summary>
	/// <param name="error">Ошибка.</param>
	public Result(string error)
	{
		Error = error;
		IsFail = true;
	}

	/// <summary>
	/// Создает успешный результат.
	/// </summary>
	/// <param name="value">Значение.</param>
	private Result(T value)
	{
		Value = value;
	}

	/// <summary>
	/// Создает успешный результат.
	/// </summary>
	/// <param name="value">Значение.</param>
	/// <returns>Результат.</returns>
	public static Result<T> Success(T value)
	{
		return new Result<T>(value);
	}

	/// <summary>
	/// Создает неуспешный результат с ошибкой.
	/// </summary>
	/// <param name="error">Ошибка.</param>
	public static implicit operator Result<T>(string error)
	{
		return Fail(error);
	}

	/// <summary>
	/// Создает успешный результат.
	/// </summary>
	/// <param name="value">Ошибка.</param>
	public static implicit operator Result<T>(T value)
	{
		return Success(value);
	}
}