using System;
using System.Reflection;
using Newtonsoft.Json;

using CommonHelpers;

namespace MyFlat {

//**************************************************************************************************
/// <summary>
/// Common base structure for API-response with message and status
/// </summary>
public partial class GeneralApiResponse: HPropertyNNBase {
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

public const string SpecialCategory_ServerError = "server_error";

public static string ErrorMsg_GeneralFailure => HLocal.TEXT(
   "The query has completed with failure.",
   "Запрос завершился неудачей." );
public static readonly Guid
   Status_GeneralFailure = new Guid( "93E0D41D-FBB8-4642-A012-EBCDB74D0FE9" );

public static string UndefinedMessage_SuccessfulCompletion =>
   HLocal.TEXT(
      "Server operation completed successfully.",
      "Серверная операция выполнилась успешно." );
public static string UndefinedErrorMessage =>
   HLocal.TEXT(
      "Undefined error of server operation.",
      "Неопределённая ошибка серверной операции." );

//--------------------------------------------------------------------------------------------------

public static GeneralApiResponse GENERAL_FAILURE =>
   new GeneralApiResponse( ErrorMsg_GeneralFailure, Status_GeneralFailure );

public static GeneralApiResponse ERROR( string messageFmt, params object?[] parameters ) =>
   new GeneralApiResponse( HString.FormatAsText( messageFmt, parameters) );
public static GeneralApiResponse ERROR( [HOptional] Guid status,
                                        string messageFmt, params object?[] parameters ) =>
   new GeneralApiResponse( HString.FormatAsText( messageFmt, parameters), status );

//==================================================================================================

[JsonIgnore]
public bool Success {
   get => Value( _NSuccess_ );
   protected set => _NSuccess_ = value;
}
[JsonIgnore]
public string? Message {
   get => _Message_;
   protected set => _Message_ = value;
}
[JsonIgnore]
[HOptionalValue]
public Guid Status {
   get => Value( _NStatus_ );
   protected set => _NStatus_ = value;
}
[JsonIgnore]
public string? SpecialCategory {
   get => _SpecialCategory_;
   protected set => _SpecialCategory_ = value;
}

[JsonIgnore] public bool HasError => !Success;
[JsonIgnore] public string ErrorMessage => GetErrorMessage();
[JsonIgnore] public bool IsServerError =>
   HString.Equals( SpecialCategory, SpecialCategory_ServerError, true );

//==================================================================================================

internal GeneralApiResponse(): this( true ) {}

//==================================================================================================

internal GeneralApiResponse(string errorMessage)
: this( false, errorMessage )
{}
/// <exception cref="ArgumentException" />
internal GeneralApiResponse([HRequired] Guid status)
: this( false, status )
{
   if ( status == Guid.Empty )
      throw new ArgumentException(HLocal.TEXT(
         "Empty GUID is not allowed for error API-response without provided message.",
         "Пустой GUID недопустим для ошибочного отклика API без указания сообщения." ));
}
/// <exception cref="ArgumentException" />
internal GeneralApiResponse([HRelOpt] string? errorMessage,[HRelOpt] Guid status)
: this( false, errorMessage, status )
{
   if ( errorMessage==null && status==Guid.Empty )
      throw new ArgumentException(HLocal.TEXT(
         "Nor error message nor status-GUID were specified for error API-response.",
         "Ни сообщение ошибки ни статус-GUID не были заданы для ошибочного отклика API." ));
}

//--------------------------------------------------------------------------------------------------

internal GeneralApiResponse(Exception e)
: this( false, MSG.ServerError( e ) )
{}

//--------------------------------------------------------------------------------------------------

internal GeneralApiResponse(bool success)
: this( success, null, Guid.Empty ) {}
internal GeneralApiResponse(bool success,string? message)
: this( success, message, Guid.Empty )
{}
internal GeneralApiResponse(bool success,[HOptional] Guid status)
: this( success, null, status )
{}
internal GeneralApiResponse(bool success,string? message,[HOptional] Guid status)
{
   Success = success;
   Message = message ?? (success ? null : UndefinedErrorMessage);
   Status = status;
}

internal GeneralApiResponse(GeneralApiResponse response)
: this( response.Success, response.Message, response.Status ) =>
   SpecialCategory = response.SpecialCategory;

//==================================================================================================

/// <exception cref="InvalidOperationException" />
internal static GeneralApiResponse CreateServerError(string errorMessage) =>
   new GeneralApiResponse( errorMessage ){
      SpecialCategory = SpecialCategory_ServerError };

//==================================================================================================

[HNotNull]
string GetErrorMessage() =>
   Success ?
      UndefinedMessage_SuccessfulCompletion :
      Message ?? UndefinedErrorMessage;

//==================================================================================================
// JSON-serializable fields:

[JsonProperty(PropertyName="response_Success",Order=Int32.MinValue)]
bool? _NSuccess_;

[JsonProperty(PropertyName="response_Message",Order=Int32.MinValue+1)]
string? _Message_;

[JsonProperty(PropertyName="response_Status",Order=Int32.MinValue+2)]
[HOptionalValue]
Guid? _NStatus_;

[JsonProperty(PropertyName="response_SpecialCategory",Order=Int32.MinValue+3)]
string? _SpecialCategory_;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
} // GeneralApiResponse
//**************************************************************************************************

} // MyFlat
