using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using EonaCat.Json;
using EonaCat.Logger.Splunk.Models;

namespace EonaCat.Logger.SplunkServer;
// This file is part of the EonaCat project(s) which is released under the Apache License.
// See the LICENSE file or go to https://EonaCat.com/License for full license details.

/// <summary>
///     Splunk Server.
/// </summary>
public class SplunkServer
{
    internal readonly object SendLock = new();
    private string _splunkHecUrl = "https://127.0.0.1:8088/services/collector/event";


    /// <summary>
    ///     Instantiate the object.
    /// </summary>
    /// <param name="splunkHecUrl">splunkHecUrl.</param>
    /// <param name="splunkHecToken">splunkHecToken.</param>
    /// <param name="httpClientHandler">httpClientHandler. (optional)</param>
    public SplunkServer(string splunkHecUrl, string splunkHecToken, HttpClientHandler httpClientHandler = null)
    {
        SplunkHecUrl = splunkHecUrl;
        SplunkHecToken = splunkHecToken;

        if (httpClientHandler == null) httpClientHandler = new HttpClientHandler();

        SplunkClientHandler = httpClientHandler;
        CreateHttpClient();
    }

    /// <summary>
    ///     SplunkHecUrl
    /// </summary>
    public string SplunkHecUrl
    {
        get => _splunkHecUrl;

        set
        {
            if (!string.IsNullOrWhiteSpace(_splunkHecUrl) && !_splunkHecUrl.ToLower().Contains("http"))
                value = $"http://{value}";
            _splunkHecUrl = value;
        }
    }

    public bool IsHttpsHecUrl => HasHecUrl && _splunkHecUrl.ToLower().StartsWith("https");

    /// <summary>
    ///     SplunkHecToken
    /// </summary>
    public string SplunkHecToken { get; set; } = "splunk-hec-token";

    public HttpClientHandler SplunkClientHandler { get; internal set; }
    public HttpClient HttpClient { get; private set; }

    /// <summary>
    ///     Determines if a HEC token is available
    /// </summary>
    public bool HasHecToken => !string.IsNullOrWhiteSpace(SplunkHecToken) && SplunkHecToken != "splunk-hec-token";

    /// <summary>
    ///     Determines if a HEC url is available
    /// </summary>
    public bool HasHecUrl => !string.IsNullOrWhiteSpace(SplunkHecUrl);

    /// <summary>
    ///     Determines if the splunk URL is local
    /// </summary>
    public bool IsLocalHost => HasHecUrl &&
                               (SplunkHecUrl.ToLower().Contains("127.0.0.1") ||
                                SplunkHecUrl.ToLower().Contains("localhost"));

    private void CreateHttpClient()
    {
        HttpClient = new HttpClient(SplunkClientHandler);
        HttpClient.BaseAddress = new Uri(SplunkHecUrl);

        // Add the HEC token to the request headers for authorization
        HttpClient.DefaultRequestHeaders.Add("Authorization", $"Splunk {SplunkHecToken}");
    }

    /// <summary>
    ///     Disables SSL validation (can be used for insecure https urls)
    ///     <note>This overwrites your own httpClientHandler</note>
    /// </summary>
    public void DisableSSLValidation()
    {
        var clientHandler = new HttpClientHandler
        {
            ServerCertificateCustomValidationCallback = (sender, cert, chain, sslPolicyErrors) => true
        };

        SplunkClientHandler = clientHandler;
        CreateHttpClient();
    }

    public async Task<HttpResponseMessage> SendAsync(SplunkPayload splunkPayload)
    {
        if (splunkPayload == null) return null;

        // Create an event object with the required fields
        var eventObject = new
        {
            @event = splunkPayload.EventData,
            sourcetype = splunkPayload.SourceType,
            host = splunkPayload.Host
        };

        // Serialize the event object to JSON
        var eventJson = JsonHelper.ToJson(eventObject);

        if (!HasHecToken) CreateHttpClient();

        // Create an HTTP content with the event data
        var content = new StringContent(eventJson, Encoding.UTF8, "application/json");

        // Send the event to Splunk
        var response = await HttpClient.PostAsync("/services/collector/event", content);

        return response;
    }
}