using Microsoft.AspNetCore.Mvc;
using Webzine.Entity;
using Webzine.Repository.Contracts;
using Webzine.WebApplication.ViewModels.Titre;

namespace Webzine.WebApplication.Controllers;

/// <summary>
/// Controleur responsable de la gestion des titres musicaux :
/// affichage des details, filtrage par style,
/// ajout de likes, commentaires et recherche.
/// </summary>
[Route("titre")]
public class TitreController : Controller
{
    private readonly ILogger<TitreController> logger;
    private readonly ITitreRepository titreRepository;

    /// <summary>
    /// Initialise une nouvelle instance du <see cref="TitreController"/>.
    /// </summary>
    /// <param name="logger">Service de journalisation injecte.</param>
    /// <param name="titreRepository">Repository des titres injecte.</param>
    public TitreController(ILogger<TitreController> logger, ITitreRepository titreRepository)
    {
        this.logger = logger;
        this.titreRepository = titreRepository;

        this.logger.LogInformation("Initialisation du controleur TitreController.");
    }

    /// <summary>
    /// Affiche le detail d'un titre specifique.
    /// </summary>
    /// <param name="id">Identifiant du titre.</param>
    /// <returns>Vue des details ou 404 si introuvable.</returns>
    [HttpGet("{id}")]
    public IActionResult Details(int id)
    {
        this.logger.LogInformation("Demande d'affichage du detail pour le titre ID {Id}.", id);

        var titre = this.titreRepository.Find(id);

        if (titre == null)
        {
            this.logger.LogWarning("Titre avec ID {Id} introuvable.", id);
            return this.RedirectToAction("Index");
        }

        var vm = new TitreDetail
        {
            Details = new TitreContent
            {
                IdTitre = titre.IdTitre,
                Libelle = titre.Libelle,
                Chronique = titre.Chronique,
                DateSortie = titre.DateSortie,
                NbLikes = titre.NbLikes,
                UrlJaquette = titre.UrlJaquette,
                UrlEcoute = titre.UrlEcoute,
                ArtisteNom = titre.Artiste?.Nom,
                Styles = titre.Styles,
                Commentaires = titre.Commentaires,
            },
            CommentForm = new TitreComment
            {
                IdTitre = titre.IdTitre,
            },
        };

        return this.View(vm);
    }

    /// <summary>
    /// Affiche les titres correspondant a un style musical donne.
    /// </summary>
    /// <param name="style">Nom du style musical.</param>
    /// <returns>Vue contenant la liste filtree.</returns>
    [HttpGet("style/{style}")]
    public IActionResult Style(string style)
    {
        this.logger.LogInformation("Recherche des titres pour le style : {Style}.", style);

        var titresFiltres = this.titreRepository.SearchByStyle(style).ToList();

        var vm = new TitreStyle
        {
            StyleName = style,
            Titres = titresFiltres.Select(MapTitreItem).ToList(),
        };

        return this.View(vm);
    }

    /// <summary>
    /// Ajoute un like a un titre.
    /// </summary>
    /// <param name="model">Modele contenant l'identifiant du titre.</param>
    /// <returns>Redirection vers la page detail.</returns>
    [HttpPost("like")]
    public IActionResult Like(TitreLike model)
    {
        this.logger.LogInformation("Ajout d'un like pour le titre ID {Id}.", model.IdTitre);

        var titre = this.titreRepository.Find(model.IdTitre);

        if (titre == null)
        {
            this.logger.LogWarning("Impossible d'ajouter un like. Titre ID {Id} introuvable.", model.IdTitre);
            return this.RedirectToAction("Index");
        }

        titre.NbLikes++;

        return this.RedirectToAction("Details", new { id = model.IdTitre });
    }

    /// <summary>
    /// Ajoute un commentaire a un titre.
    /// </summary>
    /// <param name="model">Donnees du commentaire.</param>
    /// <returns>Redirection vers la page detail.</returns>
    [HttpPost("comment")]
    public IActionResult Comment(TitreComment model)
    {
        if (!this.ModelState.IsValid)
        {
            this.logger.LogWarning("Echec de validation du modele de commentaire pour le titre ID {Id}.", model.IdTitre);
            return this.RedirectToAction("Details", new { id = model.IdTitre });
        }

        var titre = this.titreRepository.Find(model.IdTitre);

        if (titre == null)
        {
            this.logger.LogWarning("Impossible d'ajouter le commentaire. Titre ID {Id} introuvable.", model.IdTitre);
            return this.RedirectToAction("Index");
        }

        var commentaire = new Commentaire
        {
            Auteur = model.Auteur,
            Contenu = model.Contenu,
            DateCreation = DateTime.Now,
            IdTitre = model.IdTitre,
        };

        titre.Commentaires.Add(commentaire);

        this.logger.LogInformation("Commentaire ajoute avec succes au titre ID {Id}.", model.IdTitre);

        return this.RedirectToAction("Details", new { id = model.IdTitre });
    }

    private static TitreStyleItem MapTitreItem(Titre titre)
    {
        return new TitreStyleItem
        {
            IdTitre = titre.IdTitre,
            Libelle = titre.Libelle,
            ArtisteNom = titre.Artiste?.Nom,
            UrlJaquette = titre.UrlJaquette,
            Duree = titre.Duree,
        };
    }
}
