using System;
using System.Threading.Tasks;
using MediatR;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using MyHN.Application;
using MyHN.Domain;
using Website.Models;

namespace Website.Controllers
{
  /// <summary>
  /// Contrôleur pour la gestion des liens.
  /// </summary>
  public class LinksController : BaseController
  {
    private IMediator _bus;

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

    [AllowAnonymous]
    public async Task<IActionResult> Index()
    {
      var linkDtos = await _bus.Send(new GetLinksQuery());

      return View(linkDtos);
    }

    [HttpGet("{controller}/{id:guid}")]
    [AllowAnonymous]
    public async Task<IActionResult> Show(Guid id)
    {
      var linkDto = await _bus.Send(new GetLinkByIdQuery(id));
      var commentsDto = await _bus.Send(new GetCommentsByLinkQuery(id));

      return View(new ShowLinkViewModel(linkDto, commentsDto));
    }

    /// <summary>
    /// Affiche la page de publication d'un lien (ie. formulaire vide).
    /// </summary>
    /// <returns></returns>
    public IActionResult Create()
    {
      return View(new CreateLinkCommand());
    }

    /// <summary>
    /// Permet de récupérer le contenu du formulaire après envoi.
    /// </summary>
    /// <param name="command"></param>
    /// <returns></returns>
    [HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> Create(CreateLinkCommand command)
    {
      if (!ModelState.IsValid)
      {
        return View(command);
      }

      var createdLinkId = await _bus.Send(command);

      Success("Le lien a été correctement publié !");

      return RedirectToAction(nameof(Index));
    }

    // [HttpPost]
    [HttpPost("{controller}/{id:guid}/vote")]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> Vote(Guid id, VoteType direction, string redirectTo)
    {
      await _bus.Send(new VoteForLinkCommand()
      {
        LinkId = id,
        Direction = direction,
      });

      Success("Votre vote a bien été pris en compte");

      return Redirect(redirectTo);
    }

    /// <summary>
    /// Affiche le formulaire de commentaire.
    /// </summary>
    /// <param name="id"></param>
    /// <returns></returns>
    [HttpGet("{controller}/{id:guid}/comment")]
    public Task<IActionResult> Comment(Guid id)
    {
      return ShowCommentForm(id, new CommentLinkCommand(id));
    }

    private async Task<IActionResult> ShowCommentForm(Guid linkId, CommentLinkCommand command)
    {
      var link = await _bus.Send(new GetLinkByIdQuery(linkId));
      return View(new CommentFormViewModel(link, command));
    }

    [HttpPost("{controller}/{id:guid}/comment")]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> Comment(Guid id, CommentLinkCommand command)
    {
      if (!ModelState.IsValid)
      {
        return await ShowCommentForm(id, command);
      }

      await _bus.Send(command);

      return RedirectToAction(nameof(Show), new { id = id });
    }

    // [TypeFilter(typeof(CustomExceptionFilter))]
    public IActionResult Error()
    {
      throw new MyCustomException();
    }
  }

  public class MyCustomException : Exception
  {
    public MyCustomException() : base("Une erreur personnalisée !")
    {

    }
  }
}