using EonaCat.Json;
using System;
using System.Dynamic;
using System.IO;
using System.Net;
using System.Text;

namespace EonaCat.Logger.Servers.Zabbix.API;
// 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.

public class ZabbixApi
{
    /// <summary>
    /// Zabbix Api
    /// </summary>
    /// <param name="user"></param>
    /// <param name="password"></param>
    /// <param name="zabbixURL"></param>
    /// <param name="basicAuth"></param>
    public ZabbixApi(string user, string password, string zabbixURL, bool basicAuth)
    {
        _user = user;
        _password = password;
        _zabbixURL = zabbixURL;

        if (basicAuth)
        {
            _basicAuth = Convert.ToBase64String(Encoding.GetEncoding("ISO-8859-1").GetBytes(_user + ":" + _password));
        }

        _auth = null;
    }

    public ZabbixApi(string user, string password, string zabbixURL) : this(user, password, zabbixURL, false)
    {

    }

    private readonly string _user;
    private readonly string _password;
    private readonly string _zabbixURL;
    private string _auth;
    private readonly string _basicAuth = null;

    /// <summary>
    /// Determines if the user is logged in
    /// </summary>
    public bool IsLoggedIn { get; set; }

    /// <summary>
    /// Logs in the user
    /// </summary>
    public void Login()
    {
        dynamic authentication = new ExpandoObject();
        authentication.user = _user;
        authentication.password = _password;

        ZabbixApiResponse zabbixApiResponse = ResponseAsObject("user.login", authentication);

        _auth = zabbixApiResponse.Result;
        IsLoggedIn = !string.IsNullOrEmpty(_auth);
    }

    /// <summary>
    /// Logs out the user
    /// </summary>
    /// <returns></returns>
    public bool Logout()
    {
        ZabbixApiResponse zbxResponse = ResponseAsObject("user.logout", new string[] { });
        var result = zbxResponse.Result;
        return result;
    }

    /// <summary>
    /// Generic method to send a request to the Zabbix API
    /// </summary>
    /// <param name="method"></param>
    /// <param name="parameters"></param>
    /// <returns></returns>
    public string ResponseAsJson(string method, object parameters)
    {
        ZabbixApiRequest zbxRequest = new ZabbixApiRequest("2.0", method, 1, _auth, parameters);
        string jsonParameters = JsonHelper.ToJson(zbxRequest);
        return SendRequest(jsonParameters);
    }

    /// <summary>
    /// Generic method to send a request to the Zabbix API
    /// </summary>
    /// <param name="method"></param>
    /// <param name="parameters"></param>
    /// <returns></returns>
    public ZabbixApiResponse ResponseAsObject(string method, object parameters)
    {
        ZabbixApiRequest zbxRequest = new ZabbixApiRequest("2.0", method, 1, _auth, parameters);
        string jsonParameters = JsonHelper.ToJson(zbxRequest);
        return CreateResponse(SendRequest(jsonParameters));
    }

    /// <summary>
    /// Creates a ZabbixApiResponse object from a JSON string
    /// </summary>
    /// <param name="json"></param>
    /// <returns></returns>
    private ZabbixApiResponse CreateResponse(string json)
    {
        ZabbixApiResponse zbxResponse = JsonHelper.ToObject<ZabbixApiResponse>(json);
        return zbxResponse;
    }

    /// <summary>
    /// Sends a request to the Zabbix API
    /// </summary>
    /// <param name="jsonParams"></param>
    /// <returns></returns>
    private string SendRequest(string jsonParams)
    {
        WebRequest request = WebRequest.Create(_zabbixURL);

        if (_basicAuth != null)
        {
            request.Headers.Add("Authorization", "Basic " + _basicAuth);
        }

        request.ContentType = "application/json-rpc";
        request.Method = "POST";
        string jsonResult;

        using (var streamWriter = new StreamWriter(request.GetRequestStream()))
        {
            streamWriter.Write(jsonParams);
            streamWriter.Flush();
            streamWriter.Close();
        }

        WebResponse response = request.GetResponse();
        using (var streamReader = new StreamReader(response.GetResponseStream()))
        {
            jsonResult = streamReader.ReadToEnd();
        }

        return jsonResult;
    }

}
