using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using System.Security.Claims;
using UniVerse.Application.DTOs.Common;
using UniVerse.Application.DTOs.Notifications;
using UniVerse.Application.Interfaces;

namespace UniVerse.Api.Controllers;

/// <summary>Отправка и планирование уведомлений через доступные каналы.</summary>
[ApiController]
[Route("api/v1/notifications")]
[Authorize]
[Produces("application/json")]
public class NotificationsController : ControllerBase
{
    private readonly INotificationService _notifications;

    public NotificationsController(INotificationService notifications)
    {
        _notifications = notifications;
    }

    private int CurrentUserId => int.Parse(User.FindFirstValue(ClaimTypes.NameIdentifier) ?? User.FindFirstValue("sub") ?? "0");

    /// <summary>Получить уведомления текущего пользователя.</summary>
    /// <param name="pagination">Параметры пагинации.</param>
    /// <param name="cancellationToken">Токен отмены запроса.</param>
    /// <response code="200">Список уведомлений.</response>
    /// <response code="401">Требуется аутентификация.</response>
    [HttpGet]
    [ProducesResponseType(typeof(PagedResult<UserNotificationDto>), StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status401Unauthorized)]
    public async Task<ActionResult<PagedResult<UserNotificationDto>>> GetMine(
        [FromQuery] PaginationRequest pagination,
        CancellationToken cancellationToken) =>
        Ok(await _notifications.GetUserNotificationsAsync(CurrentUserId, pagination, cancellationToken));

    /// <summary>Отметить все уведомления текущего пользователя как прочитанные.</summary>
    /// <param name="cancellationToken">Токен отмены запроса.</param>
    /// <response code="204">Уведомления отмечены прочитанными.</response>
    /// <response code="401">Требуется аутентификация.</response>
    [HttpPatch("read-all")]
    [ProducesResponseType(StatusCodes.Status204NoContent)]
    [ProducesResponseType(StatusCodes.Status401Unauthorized)]
    public async Task<IActionResult> MarkAllRead(CancellationToken cancellationToken)
    {
        await _notifications.MarkAllReadAsync(CurrentUserId, cancellationToken);
        return NoContent();
    }

    /// <summary>Отправить уведомление немедленно.</summary>
    /// <remarks>
    /// Канал задаётся строкой, например `email`. Новые провайдеры добавляются через `INotificationProvider`.
    /// </remarks>
    /// <param name="request">Канал, получатель, тема и текст уведомления.</param>
    /// <response code="202">Уведомление принято к отправке.</response>
    /// <response code="401">Требуется аутентификация.</response>
    /// <response code="403">Требуется роль Admin.</response>
    [Authorize(Roles = "Admin")]
    [HttpPost("send")]
    [ProducesResponseType(StatusCodes.Status202Accepted)]
    [ProducesResponseType(StatusCodes.Status401Unauthorized)]
    [ProducesResponseType(StatusCodes.Status403Forbidden)]
    public async Task<IActionResult> Send([FromBody] SendNotificationRequest request, CancellationToken cancellationToken)
    {
        var message = new NotificationMessage(
            request.Channel,
            request.Recipient,
            request.Subject,
            request.Body,
            request.RecipientName,
            request.Metadata);

        await _notifications.SendAsync(message, cancellationToken);
        return Accepted();
    }

    /// <summary>Запланировать отложенную отправку уведомления через Quartz.NET.</summary>
    /// <param name="request">Уведомление и момент отправки.</param>
    /// <response code="202">Уведомление поставлено в очередь Quartz.NET.</response>
    /// <response code="401">Требуется аутентификация.</response>
    /// <response code="403">Требуется роль Admin.</response>
    [Authorize(Roles = "Admin")]
    [HttpPost("schedule")]
    [ProducesResponseType(typeof(ScheduledNotificationResponse), StatusCodes.Status202Accepted)]
    [ProducesResponseType(StatusCodes.Status401Unauthorized)]
    [ProducesResponseType(StatusCodes.Status403Forbidden)]
    public async Task<ActionResult<ScheduledNotificationResponse>> Schedule([FromBody] ScheduleNotificationRequest request, CancellationToken cancellationToken)
    {
        var response = await _notifications.ScheduleAsync(request, cancellationToken);
        return Accepted(response);
    }
}
