// {Leslie}

using _Combo;
using _Core;
using System;

namespace Seayoo.ComboSDK.Windows.Store.Networking
{
    class SeatooStoreResponse<T>
    {
        [Serializable]
        class _ServerError
        {
            public string error;
            public string message;
        }

        public int StatusCode { get; private set; }
        public string TraceId { get; private set; }

        private Result<T, InternalError> result;

        public static SeatooStoreResponse<T> CreateResponse(
            HttpResponse response,
            string url = ""
        ) {
            return CreateResponse<T>(response, resp => resp, url);
        }

        public static SeatooStoreResponse<T> CreateResponse<U>(
            HttpResponse response,
            Func<U, T> dataConvertor, string url = ""
        )
        {
            string traceId;
            if (response.IsSuccess)
            {
                var data = response.Body.ToJson<U>();
                response.Headers.TryGetValue("x-trace-id", out traceId);

                return new SeatooStoreResponse<T>
                {
                    StatusCode = response.StatusCode,
                    TraceId = traceId,
                    result = Result<T, InternalError>.CreateSuccess(dataConvertor(data))
                };
            }
            else if (response.IsHttpError)
            {
                response.Headers.TryGetValue("x-trace-id", out traceId);
                try
                {
                    var serverError = response.Body.ToJson<_ServerError>();
                    return new SeatooStoreResponse<T>
                    {
                        StatusCode = response.StatusCode,
                        TraceId = traceId,
                        result = Result<T, InternalError>.CreateFail(
                            new InternalError(
                                new ServerError(statusCode: response.StatusCode,
                                                url: url,
                                                error: serverError.error, 
                                                errorMsg: serverError.message,
                                                traceId: traceId)
                            )
                        ),
                    };
                }
                catch (Exception)
                {
                    return new SeatooStoreResponse<T>
                    {
                        StatusCode = response.StatusCode,
                        TraceId = traceId,
                        result = Result<T, InternalError>.CreateFail(
                            new InternalError(
                                new ServerError(statusCode: response.StatusCode,
                                                url: url,
                                                traceId: traceId)
                            )
                        ),
                    };
                }
            }
            else if (response.IsNetworkError)
            {
                return new SeatooStoreResponse<T>
                {
                    StatusCode = response.StatusCode,
                    TraceId = null,
                    result = Result<T, InternalError>.CreateFail(
                            new InternalError(
                                new NetworkError(url: url, message: response.Error)
                            )
                        ),
                };
            }
            return new SeatooStoreResponse<T>
            {
                result = Result<T, InternalError>.CreateFail(
                    new InternalError(I18n.T("unknown_error"))
                ),
            };
        }

        public T Data => result.Data;

        public InternalError Error => result.Error;

        public bool IsSuccess => result.IsSuccess;
    }
}
