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

namespace KernelRecordsMVC.Web.Controllers;

public class OrderController : Controller
{
    private readonly KernelRecordsContext _context;

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


    // ==========================================
    // ADD PRODUCT TO ORDER
    // UC007
    // ==========================================

    [HttpGet]
    public IActionResult AddProduct(long id)
    {
        var userId = GetUserId();

        if (userId == null)
            return RedirectToAction(
                "Login",
                "Account");

        var product = _context.Products
            .Include(p => p.Release)
            .FirstOrDefault(p => p.ProductId == id);

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

        if (product.Stock <= 0)
        {
            TempData["Error"] =
                "This product is currently out of stock.";

            return RedirectToAction(
                "Details",
                "Release",
                new { id = product.ReleaseId });
        }


        // Find an existing pending order.
        var order = _context.Orders
            .Include(o => o.OrderProducts)
            .FirstOrDefault(o =>
                o.UserId == userId.Value &&
                o.Status == OrderStatusType.PENDING);


        // If there is no pending order, create one.
        if (order == null)
        {
            order = new Order
            {
                UserId = userId.Value,
                PaymentMethod = PaymentMethodType.CARD,
                PurchaseDate = DateTime.Today,
                PointsEarned = 0,
                PointsUsed = null,
                Status = OrderStatusType.PENDING
            };

            _context.Orders.Add(order);

            _context.SaveChanges();
        }


        // Check whether product is already in cart.
        var existingItem = order.OrderProducts
            .FirstOrDefault(x =>
                x.ProductId == product.ProductId);


        if (existingItem != null)
        {
            if (existingItem.Quantity + 1 >
                product.Stock)
            {
                TempData["Error"] =
                    "There is not enough stock available.";

                return RedirectToAction(
                    "Details",
                    "Release",
                    new { id = product.ReleaseId });
            }

            existingItem.Quantity++;
        }
        else
        {
            var discount = _context.ModificationProducts
                .Include(mp => mp.Modification)
                .Where(mp =>
                    mp.ProductId == product.ProductId &&
                    mp.Modification.TypeOfModification ==
                    ModificationType.DISCOUNT &&
                    mp.Modification.Discount.HasValue &&
                    mp.Modification.Discount.Value > 0)
                .Select(mp => mp.Modification)
                .OrderByDescending(m => m.DateModified)
                .FirstOrDefault();

            var priceAtPurchase = product.Price;

            if (discount != null)
            {
                priceAtPurchase =
                    product.Price -
                    (product.Price * discount.Discount!.Value / 100m);

                priceAtPurchase = Math.Round(
                    priceAtPurchase,
                    2);
            }

            var orderProduct = new OrderProduct
            {
                OrderId = order.OrderId,

                ProductId = product.ProductId,

                PriceAtPurchase = product.Price,

                Quantity = 1
            };

            _context.OrderProducts.Add(orderProduct);
        }

        _context.SaveChanges();


        return RedirectToAction(nameof(Cart));
    }


    // ==========================================
    // CART
    // ==========================================

    [HttpGet]
    public IActionResult Cart()
    {
        var userId = GetUserId();

        if (userId == null)
        {
            return RedirectToAction(
                "Login",
                "Account");
        }


        var order = _context.Orders
            .Include(o => o.OrderProducts)
                .ThenInclude(op => op.Product)
                    .ThenInclude(p => p.Release)
            .FirstOrDefault(o =>
                o.UserId == userId.Value &&
                o.Status == OrderStatusType.PENDING);


        var viewModel = new CartViewModel();


        if (order != null)
        {
            viewModel.Items = order.OrderProducts
                .Select(op => new CartItemViewModel
                {
                    ProductId = op.ProductId,

                    ReleaseId =
                        op.Product.ReleaseId,

                    ReleaseTitle =
                        op.Product.Release.Title,

                    Format =
                        op.Product.Format.ToString(),

                    Price =
                        op.PriceAtPurchase,

                    Quantity =
                        op.Quantity,

                    Stock =
                        op.Product.Stock,
                    
                    CoverPhoto = op.Product.Release.CoverPhoto
                })
                .ToList();
        }


        return View(viewModel);
    }


    // ==========================================
    // REMOVE PRODUCT
    // ==========================================

    [HttpPost]
    [ValidateAntiForgeryToken]
    public IActionResult RemoveProduct(long id)
    {
        var userId = GetUserId();

        if (userId == null)
            return RedirectToAction(
                "Login",
                "Account");


        var item = _context.OrderProducts
            .Include(x => x.Order)
            .FirstOrDefault(x =>
                x.ProductId == id &&
                x.Order.UserId == userId.Value &&
                x.Order.Status ==
                    OrderStatusType.PENDING);


        if (item != null)
        {
            _context.OrderProducts.Remove(item);
            _context.SaveChanges();
        }


        return RedirectToAction(nameof(Cart));
    }


    // ==========================================
    // UPDATE QUANTITY
    // ==========================================

    [HttpPost]
    [ValidateAntiForgeryToken]
    public IActionResult UpdateQuantity(
        long id,
        long quantity)
    {
        var userId = GetUserId();

        if (userId == null)
            return RedirectToAction(
                "Login",
                "Account");


        if (quantity <= 0)
        {
            return RemoveProduct(id);
        }


        var item = _context.OrderProducts
            .Include(x => x.Order)
            .Include(x => x.Product)
            .FirstOrDefault(x =>
                x.ProductId == id &&
                x.Order.UserId == userId.Value &&
                x.Order.Status ==
                    OrderStatusType.PENDING);


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


        if (quantity > item.Product.Stock)
        {
            TempData["Error"] =
                "The requested quantity exceeds available stock.";

            return RedirectToAction(nameof(Cart));
        }


        item.Quantity = quantity;

        _context.SaveChanges();


        return RedirectToAction(nameof(Cart));
    }


    // ==========================================
    // USER ID
    // ==========================================

    private long? GetUserId()
    {
        var userId = HttpContext.Session.GetInt32("UserId");

        if (userId.HasValue)
            return userId.Value;

        return null;
    }
}