using System;
using System.Threading.Tasks;
using MediatR;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using MyHN.Application;

namespace Api.Controllers
{
  [ApiController]
  [Route("api/links")]
  public class LinksController : ControllerBase
  {
    private readonly IMediator _bus;

    public LinksController(IMediator bus)
    {
      _bus = bus;
    }

    /// <summary>
    /// Récupère tous les liens publiés depuis la nuit des temps.
    /// </summary>
    /// <returns></returns>
    [HttpGet]
    public async Task<LinkDto[]> GetLinks()
    {
      return await _bus.Send(new GetLinksQuery());
    }

    /// <summary>
    /// Récupère un lien unitairement.
    /// </summary>
    /// <param name="id"></param>
    /// <returns></returns>
    [HttpGet("{id:guid}")]
    [ProducesResponseType(typeof(LinkDto), StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    public async Task<LinkDto> GetLinkById(Guid id)
    {
      return await _bus.Send(new GetLinkByIdQuery(id));
    }

    /// <summary>
    /// Récupère tous les commentaires d'un lien.
    /// </summary>
    /// <param name="id"></param>
    /// <returns></returns>
    [HttpGet("{id:guid}/comments")]
    public async Task<CommentDto[]> GetLinkComments(Guid id)
    {
      return await _bus.Send(new GetCommentsByLinkQuery(id));
    }

    /// <summary>
    /// Permet la publication d'un nouveau lien sur la plateforme.
    /// </summary>
    /// <param name="command"></param>
    /// <returns></returns>
    [HttpPost]
    [Authorize]
    [ProducesResponseType(StatusCodes.Status400BadRequest)]
    [ProducesResponseType(StatusCodes.Status401Unauthorized)]
    [ProducesResponseType(StatusCodes.Status201Created)]
    public async Task<IActionResult> CreateLink(CreateLinkCommand command)
    {
      var linkId = await _bus.Send(command);
      return CreatedAtAction(nameof(GetLinkById), new { id = linkId }, null);
    }

    /// <summary>
    /// Permet d'upvoter un lien.
    /// </summary>
    /// <param name="id"></param>
    /// <returns></returns>
    [HttpPut("{id:guid}/upvote")]
    [Authorize]
    [ProducesResponseType(StatusCodes.Status204NoContent)]
    [ProducesResponseType(StatusCodes.Status401Unauthorized)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    public async Task<IActionResult> Upvote(Guid id)
    {
      await _bus.Send(new VoteForLinkCommand
      {
        LinkId = id,
        Direction = MyHN.Domain.VoteType.Up,
      });
      return NoContent();
    }

    /// <summary>
    /// Permet de downvoter un lien.
    /// </summary>
    /// <param name="id"></param>
    /// <returns></returns>
    [HttpPut("{id:guid}/downvote")]
    [Authorize]
    [ProducesResponseType(StatusCodes.Status204NoContent)]
    [ProducesResponseType(StatusCodes.Status401Unauthorized)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    public async Task<IActionResult> Downvote(Guid id)
    {
      await _bus.Send(new VoteForLinkCommand
      {
        LinkId = id,
        Direction = MyHN.Domain.VoteType.Down,
      });
      return NoContent();
    }
  }
}