﻿using KernelRecordsMVC.Domain.Enums;
using KernelRecordsMVC.Infrastructure.Data;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;

namespace KernelRecordsMVC.Web.Controllers;

public class ReleaseController : Controller
{
    private readonly KernelRecordsContext _context;

    public ReleaseController(KernelRecordsContext context)
    {
        _context = context;
    }

    // =========================================================
    // BROWSE RELEASES
    // =========================================================

    public IActionResult Index(
        string? search,
        string? genre,
        string? format,
        string? type,
        string? sort)
    {
        var query = _context.Releases
            .Include(r => r.Products)
            .Include(r => r.ReleaseArtists)
                .ThenInclude(ra => ra.Artist)
            .Include(r => r.Album)
            .Include(r => r.SingleRelease)
            .AsQueryable();

        // SEARCH
        if (!string.IsNullOrWhiteSpace(search))
        {
            search = search.Trim();

            query = query.Where(r =>
                r.Title.ToLower().Contains(search.ToLower()) ||
                r.Genre.ToLower().Contains(search.ToLower()) ||
                r.ReleaseArtists.Any(ra =>
                    ra.Artist.ArtistName.ToLower()
                        .Contains(search.ToLower())));
        }

        // GENRE
        if (!string.IsNullOrWhiteSpace(genre))
        {
            query = query.Where(r =>
                r.Genre.ToLower() == genre.ToLower());
        }

        // FORMAT
        if (!string.IsNullOrWhiteSpace(format))
        {
            query = query.Where(r =>
                r.Products.Any(p =>
                    p.Format.ToString() == format));
        }

        // TYPE
        if (!string.IsNullOrWhiteSpace(type))
        {
            if (type.Equals("Album", StringComparison.OrdinalIgnoreCase))
            {
                query = query.Where(r => r.Album != null);
            }
            else if (type.Equals("Single", StringComparison.OrdinalIgnoreCase))
            {
                query = query.Where(r => r.SingleRelease != null);
            }
        }

        // SORT
        query = sort switch
        {
            "titleDesc" =>
                query.OrderByDescending(r => r.Title),

            "newest" =>
                query.OrderByDescending(r => r.ReleaseDate),

            "oldest" =>
                query.OrderBy(r => r.ReleaseDate),

            "format" =>
                query.OrderBy(r =>
                    r.Products
                        .Select(p => p.Format.ToString())
                        .FirstOrDefault()),

            "priceAsc" =>
                query.OrderBy(r =>
                    r.Products
                        .Select(p => (decimal?)p.Price)
                        .Min()),

            "priceDesc" =>
                query.OrderByDescending(r =>
                    r.Products
                        .Select(p => (decimal?)p.Price)
                        .Max()),

            _ =>
                query.OrderBy(r => r.Title)
        };

        var releases = query.ToList();

        ViewBag.Search = search;
        ViewBag.Genre = genre;
        ViewBag.Format = format;
        ViewBag.Type = type;
        ViewBag.Sort = sort;

        ViewBag.Genres = _context.Releases
            .Select(r => r.Genre)
            .Distinct()
            .OrderBy(g => g)
            .ToList();

        ViewBag.Formats = Enum
            .GetValues<ProductFormat>()
            .Select(x => x.ToString())
            .ToList();

        return View(releases);
    }


    // =========================================================
    // DETAILS
    // =========================================================

    public IActionResult Details(long id)
    {
        var release = _context.Releases
            .Include(r => r.ReleaseArtists)
            .ThenInclude(ra => ra.Artist)

            .Include(r => r.Products)
            .ThenInclude(p => p.ModificationProducts)
            .ThenInclude(mp => mp.Modification)

            .Include(r => r.Album)
            .ThenInclude(a => a.AlbumSongs)
            .ThenInclude(albumSong => albumSong.Song)
            .ThenInclude(song => song.SongArtists)
            .ThenInclude(songArtist => songArtist.Artist)

            .Include(r => r.SingleRelease)

            .FirstOrDefault(r => r.ReleaseId == id);

        if (release == null)
            return NotFound();

        return View(release);
    }
}