using System.ComponentModel.DataAnnotations;
using System.Threading;
using System.Threading.Tasks;
using AsbCloudApp.Data;
using AsbCloudApp.Exceptions;
using AsbCloudApp.Repositories;
using AsbCloudApp.Requests;
using AsbCloudApp.Services.Notifications;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;

namespace AsbCloudWebApi.Controllers;

/// <summary>
/// Уведомления
/// </summary>
[ApiController]
[Authorize]
[Route("api/notification")]
public class NotificationController : ControllerBase
{
	private readonly INotificationService notificationService;
	private readonly INotificationRepository notificationRepository;

	public NotificationController(INotificationService notificationService,
		INotificationRepository notificationRepository)
	{
		this.notificationService = notificationService;
		this.notificationRepository = notificationRepository;
	}

	/// <summary>
	/// Отправка уведомления
	/// </summary>
	/// <param name="idUser">Id пользователя</param>
	/// <param name="idNotificationCategory">Id категории уведомления. Допустимое значение параметра: 1</param>
	/// <param name="title">Заголовок уведомления</param>
	/// <param name="message">Сообщение уведомления</param>
	/// <param name="idNotificationTransport">Id типа доставки уведомления. Допустимое значение: 0</param>
	/// <param name="cancellationToken"></param>
	/// <returns></returns>
	[HttpPost]
	[Route("send")]
	public async Task<IActionResult> SendAsync([Required] int idUser,
		[Required]
		[Range(minimum: 1, maximum: 1, ErrorMessage = "Id категории уведомления недоступно. Допустимые: 1")]
		int idNotificationCategory,
		[Required] string title,
		[Required] string message,
		[Required]
		[Range(minimum: 0, maximum: 0, ErrorMessage = "Id способа отправки уведомления недоступно. Допустимые: 0")]
		int idNotificationTransport,
		CancellationToken cancellationToken)
	{
		await notificationService.NotifyAsync(idUser,
			idNotificationCategory, 
			title, 
			message,
			idNotificationTransport,
			cancellationToken);
		
		return Ok();
	}
	
	/// <summary>
	/// Обновление уведомления
	/// </summary>
	/// <param name="idNotification">Id уведомления</param>
	/// <param name="isRead">Прочитано ли уведомление</param>
	/// <param name="cancellationToken"></param>
	/// <returns></returns>
	[HttpPut]
	[Route("update")]
	public async Task<IActionResult> UpdateAsync([Required] int idNotification,
		[Required] bool isRead,
		CancellationToken cancellationToken)
	{
		await notificationService.UpdateNotificationAsync(idNotification,
			isRead,
			cancellationToken);
		
		return Ok();
	}
	
	/// <summary>
	/// Получение уведомления по Id
	/// </summary>
	/// <param name="idNotification">Id уведомления</param>
	/// <param name="cancellationToken"></param>
	/// <returns></returns>
	[HttpGet]
	[Route("get/{idNotification}")]
	[ProducesResponseType(typeof(NotificationDto), (int)System.Net.HttpStatusCode.OK)]
	public async Task<IActionResult> GetAsync([Required] int idNotification,
		CancellationToken cancellationToken)
	{
		var notification = await notificationRepository.GetOrDefaultAsync(idNotification, cancellationToken);

		if (notification is null)
		{
			return BadRequest(ArgumentInvalidException.MakeValidationError(nameof(idNotification),
				"Уведомление не найдено"));	
		}

		return Ok(notification);
	}
	
	/// <summary>
	/// Получение списка уведомлений
	/// </summary>
	/// <param name="request">Параметры запроса</param>
	/// <param name="cancellationToken"></param>
	/// <returns></returns>
	[HttpGet]
	[Route("getList")]
	[ProducesResponseType(typeof(PaginationContainer<NotificationDto>), (int)System.Net.HttpStatusCode.OK)]
	public async Task<IActionResult> GetListAsync([FromQuery] NotificationRequest request,
		CancellationToken cancellationToken)
	{
		int? idUser = User.GetUserId();

		if (!idUser.HasValue)
			return Forbid();
		
		var result = await notificationRepository.GetNotificationsAsync(idUser.Value,
			request,
			cancellationToken);

		return Ok(result);
	}

	/// <summary>
	/// Удаление уведомления
	/// </summary>
	/// <param name="idNotification">Id уведомления</param>
	/// <param name="cancellationToken"></param>
	/// <returns></returns>
	[HttpDelete]
	[Route("delete")]
	public async Task<IActionResult> DeleteAsync([Required] int idNotification,
		CancellationToken cancellationToken)
	{
		await notificationRepository.DeleteAsync(idNotification,
			cancellationToken);

		return Ok();
	}
}