using System.Collections.Generic;
using System;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.Extensions.Options;

namespace DigitalData.Core.Legacy.Client
{
    public class BaseHttpClientService
    {
        protected readonly HttpClient _client;
        protected readonly CookieContainer _cookies;

        public string Uri { get; protected set; }

        public BaseHttpClientService(HttpClient client, CookieContainer cookieContainer, IOptions<HttpClientOptions> clientOptions)
        {
            _client = client;
            _cookies = cookieContainer;
            Uri = clientOptions.Value.Uri;
        }

        public CookieCollection GetCookies(string route = "") => _cookies.GetCookies(uri: new Uri(Uri + route));

        public async Task<HttpResponseMessage> FetchAsync(
            string route = "",
            HttpMethod method = null,
            HttpContent body = null,
            Dictionary<string, string> form = null,
            bool sendWithCookie = true,
            bool saveCookie = true
        )
        {
            // set default HTTP method as GET
            if(method is null)
                method = HttpMethod.Get;            

            // create URL
            var requestUriStr = Uri + route;
            var requestUri = new Uri(requestUriStr);

            var requestMessage = new HttpRequestMessage(method, requestUriStr);

            // Add cookie to request
            if (sendWithCookie)
            {
                var cookieHeader = _cookies.GetCookieHeader(requestUri);
                if (!string.IsNullOrWhiteSpace(cookieHeader))
                {
                    requestMessage.Headers.Add("Cookie", cookieHeader);
                }
            }

            // Add body content if provided
            if (body != null && form != null)
                throw new InvalidOperationException("Body content and form data cannot both be set.");
            else if (body != null)
                requestMessage.Content = body;
            else if (form != null)
                requestMessage.Content = new FormUrlEncodedContent(form);

            var response = await _client.SendAsync(requestMessage);

            // Add response cookies to cookies
            if (saveCookie)
                if (response.Headers.TryGetValues("Set-Cookie", out var cookies))
                    foreach (var cookie in cookies)
                        _cookies.SetCookies(requestUri, cookie);

            return response;
        }
    }
}