using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

namespace UVC.Data
{
    /// <summary>
    /// HTTP 응답 문자열을 파싱하여 성공 여부를 확인하고 실제 데이터를 추출하는 규칙을 정의하는 클래스입니다.
    /// </summary>
    /// <remarks>
    /// 이 클래스는 주로 JSON 형식의 응답에서 특정 키 값을 기준으로 작업의 성공 여부를 판단하고,
    /// 성공한 경우 데이터가 담긴 부분을 추출하는 데 사용됩니다.
    /// </remarks>
    public class HttpResponseMask
    {
        /// <summary>
        /// 응답에서 성공 여부를 나타내는 상태 메시지의 키 이름입니다. 기본값은 "message"입니다.
        /// </summary>
        private string successKey = "message";
        /// <summary>
        /// 응답에서 성공 상태를 나타내는 특정 값입니다. 이 값과 <see cref="successKey"/>의 값이 일치하면 성공으로 간주합니다. 기본값은 "success"입니다.
        /// </summary>
        private string successValue = "success";
        /// <summary>
        /// 응답에서 실제 데이터 페이로드를 담고 있는 키 이름입니다. 기본값은 "data"입니다.
        /// </summary>
        private string dataKey = "data";

        /// <summary>
        /// 응답에서 성공 여부를 나타내는 상태 메시지의 키 이름을 가져옵니다.
        /// </summary>
        public string SuccessKey => successKey;
        /// <summary>
        /// 응답에서 성공 상태를 나타내는 특정 값을 가져옵니다.
        /// </summary>
        public string SuccessValue => successValue;
        /// <summary>
        /// 응답에서 실제 데이터 페이로드를 담고 있는 키 이름을 가져옵니다.
        /// </summary>
        public string DataKey => dataKey;

        /// <summary>
        /// 기본값("message", "success", "data")으로 <see cref="HttpResponseMask"/> 클래스의 새 인스턴스를 초기화합니다.
        /// </summary>
        public HttpResponseMask() { }

        /// <summary>
        /// 지정된 키 값으로 <see cref="HttpResponseMask"/> 클래스의 새 인스턴스를 초기화합니다.
        /// </summary>
        /// <param name="successKey">성공 여부 판단에 사용될 키 이름입니다.</param>
        /// <param name="successValue">성공 상태를 나타내는 값입니다.</param>
        /// <param name="dataKey">실제 데이터가 포함된 키 이름입니다.</param>
        public HttpResponseMask(string successKey, string successValue, string dataKey)
        {
            this.successKey = successKey;
            this.successValue = successValue;
            this.dataKey = dataKey;
        }

        /// <summary>
        /// 제공된 HTTP 응답 문자열에 마스크 규칙을 적용하여 파싱 결과를 반환합니다.
        /// </summary>
        /// <param name="response">파싱할 HTTP 응답 문자열입니다. JSON 형식이어야 합니다.</param>
        /// <returns>
        /// 파싱 결과를 담고 있는 <see cref="HttpResponseResult"/> 객체입니다.
        /// <see cref="HttpResponseResult.IsSuccess"/>가 <c>true</c>이면, <see cref="HttpResponseResult.Data"/>에 추출된 데이터 문자열이 포함됩니다.
        /// <see cref="HttpResponseResult.IsSuccess"/>가 <c>false</c>이면, <see cref="HttpResponseResult.Message"/>에 원본 응답 문자열이 포함될 수 있습니다.
        /// </returns>
        /// <remarks>
        /// 이 메서드는 먼저 응답 문자열을 <see cref="JObject"/>로 파싱합니다.
        /// 그 다음, <see cref="SuccessKey"/>에 해당하는 토큰 값과 <see cref="SuccessValue"/>를 비교하여 (대소문자 구분 없이) 성공 여부를 판단합니다.
        /// 성공한 경우, <see cref="DataKey"/>에 해당하는 토큰의 문자열 값을 <see cref="HttpResponseResult.Data"/>에 설정하고 <see cref="HttpResponseResult.IsSuccess"/>를 <c>true</c>로 설정합니다.
        /// 만약 <see cref="SuccessKey"/>에 해당하는 토큰 값과 <see cref="SuccessValue"/>를 비교하여 같지만 <see cref="DataKey"/>에 해당하는 토큰이 없거나 null인 경우에도 <see cref="HttpResponseResult.IsSuccess"/>를 <c>false</c>로 설정합니다.
        /// 실패한 경우, 원본 응답 문자열을 <see cref="HttpResponseResult.Message"/>에 설정하고 <see cref="HttpResponseResult.IsSuccess"/>를 <c>false</c>로 설정합니다.
        /// </remarks>
        public HttpResponseResult Apply(string response)
        {
            JObject responseObject = JObject.Parse(response);
            if (responseObject.TryGetValue(successKey, out JToken? successToken) &&
                responseObject.TryGetValue(dataKey, out JToken? dataToken) &&
                successToken?.ToString().ToLower() == successValue.ToLower()) // successValue 비교 시에도 ToLower() 추가하여 일관성 유지
            {
                // 성공적인 응답 처리 로직
                if (dataToken != null) return new HttpResponseResult(true, dataToken!.ToString(Formatting.None)); // 실제로는 dataKey에 해당하는 데이터만 반환할 수 있습니다.
            }
            return new HttpResponseResult(false, null, response); // 실패한 응답 처리 로직
        }
    }
}
