﻿using System;
using System.Text;
using System.Net.Http;
using System.Threading.Tasks;
using Newtonsoft.Json;
using ESP.Slack.Models;
using ESP.Slack.Exceptions;

namespace ESP.Slack
{
    public class SlackClient
    {
		private static Uri _webhookUri;

		private static string _username;

		private static string _icon;

		public SlackClient()
		{ }

		public SlackClient(Uri webhookUri)
		{
			_webhookUri = webhookUri;
		}

		public SlackClient(SlackClientConfig config)
		{
			SetConfig(config);
		}

		public static void SetWebhookUri(Uri webhookUri) => _webhookUri = webhookUri;
		public static void SetWebhookUri(string webhookUri) => _webhookUri = new Uri(webhookUri);

		public static void SetConfig(SlackClientConfig config)
		{
			_webhookUri = config.WebhookUri;
			_username = config.Username;
			_icon = config.IconEmoji;
		}

		public static Uri GetWebhookUri() => _webhookUri;


		async public Task SendAsync(string text, string username = null, string icon = null)
		{
			if (_webhookUri == null) throw new SlackArgumentNullException(nameof(_webhookUri), "Value cannot be null. Call 'SlackClient.SetWebhookUri(<url>)'.");

			if (string.IsNullOrEmpty(text)) throw new SlackArgumentNullException(nameof(text), "Value cannot be null.");

			if (!string.IsNullOrEmpty(_username)) username = _username;
			if (!string.IsNullOrEmpty(_icon)) icon = _icon;

			SlackMessage message = new SlackMessage(text, username ?? "SlackClient", icon);

			string payload = JsonConvert.SerializeObject(message);

			using (HttpClient client = new HttpClient())
			{
				await client.PostAsync(_webhookUri, new StringContent(payload, Encoding.UTF8, "application/json")); 
			}
		}

		async public Task SendAsync(SlackMessage message)
		{ 
			if (_webhookUri == null) throw new SlackArgumentNullException(nameof(_webhookUri), "Value cannot be null. Call 'SlackClient.SetWebhookUri(<url>)' from StartUp.");

			if (message == null) throw new SlackArgumentNullException(nameof(message), "Value cannot be null.");

			if (string.IsNullOrEmpty(message.Text)) throw new SlackArgumentNullException(nameof(message.Text), "Value cannot be null.");


			if (message.Attachments != null && message.Attachments.Count > 0)
			{
				if (message.Attachments.Count > 20) throw new SlackArgumentNullException("Exceeded maximum amount of attachments in a message (20)", nameof(message.Attachments));

				foreach (var attachment in message.Attachments)
				{
					if (string.IsNullOrEmpty(attachment.Fallback)) throw new SlackArgumentNullException(nameof(attachment.Fallback), "Value cannot be null");
					if (string.IsNullOrEmpty(attachment.CallbackId)) throw new SlackArgumentNullException(nameof(attachment.CallbackId), "Value cannot be null");

					if (attachment.Actions != null && attachment.Actions.Count > 0)
					{
						if (attachment.Actions.Count > 5) throw new SlackException("Exceeded maxium amount of actions in an attachment (5)");

						foreach (var action in attachment.Actions)
						{
							if (string.IsNullOrEmpty(action.Name)) throw new SlackArgumentNullException(nameof(action.Name), "Value cannot be null");
							if (string.IsNullOrEmpty(action.Text)) throw new SlackArgumentNullException(nameof(action.Text), "Value cannot be null");
							if (action.Type == null) throw new SlackArgumentNullException(nameof(action.Type), "Value cannot be null");

							if (action.Confirm != null)
							{
								if (string.IsNullOrEmpty(action.Confirm.Text)) throw new SlackArgumentNullException(nameof(action.Confirm.Text), "Value cannot be nul.");
							}
						}
					}
				}
			}

			string payload = JsonConvert.SerializeObject(message);

			using (HttpClient client = new HttpClient())
			{
				await client.PostAsync(_webhookUri, new StringContent(payload, Encoding.UTF8, "application/json"));
			}
		}

	}
}
