using FruitBank.Common.Enums;
using LinqToDB;
using Microsoft.AspNetCore.Mvc;
using Nop.Core;
using Nop.Plugin.Misc.FruitBankPlugin.Domains.DataLayer;
using Nop.Services.Customers;
using Nop.Web.Framework.Controllers;

namespace Nop.Plugin.Misc.FruitBankPlugin.Controllers;

public class CustomerPreorderController : BasePluginController
{
    private readonly IWorkContext _workContext;
    private readonly ICustomerService _customerService;
    private readonly PreorderDbContext _preorderDbContext;
    private readonly FruitBankDbContext _dbContext;

    public CustomerPreorderController(
        IWorkContext workContext,
        ICustomerService customerService,
        PreorderDbContext preorderDbContext,
        FruitBankDbContext dbContext)
    {
        _workContext = workContext;
        _customerService = customerService;
        _preorderDbContext = preorderDbContext;
        _dbContext = dbContext;
    }

    [HttpGet]
    public async Task<IActionResult> List()
    {
        var customer = await _workContext.GetCurrentCustomerAsync();
        if (await _customerService.IsGuestAsync(customer))
            return Challenge();

        // Load this customer's preorders, newest first
        var preorders = await _preorderDbContext.Preorders
            .GetAllByCustomerIdAsync(customer.Id, false)
            .OrderByDescending(p => p.CreatedOnUtc)
            .ToListAsync();

        var allItems = await _preorderDbContext.PreorderItems.GetAll()
            .Where(i => preorders.Select(p => p.Id).Contains(i.PreorderId))
            .ToListAsync();

        // Resolve product names
        var productIds  = allItems.Select(i => i.ProductId).Distinct().ToList();
        var productDtos = await _dbContext.ProductDtos
            .GetAll(false)
            .Where(p => productIds.Contains(p.Id))
            .ToListAsync();
        var productById = productDtos.ToDictionary(p => p.Id);

        var rows = preorders.Select(p =>
        {
            var items = allItems.Where(i => i.PreorderId == p.Id).ToList();

            // Derive status from quantities (enum reads unreliable in LinqToDB)
            var allFulfilled = items.Any() && items.All(i => i.FulfilledQuantity >= i.RequestedQuantity);
            var anyFulfilled = items.Any(i => i.FulfilledQuantity > 0);
            var allDropped   = items.Any() && items.All(i => i.FulfilledQuantity == 0 &&
                                                              i.RequestedQuantity > 0);

            var effectiveStatus = (int)p.Status != 0 ? p.Status
                : allFulfilled  ? PreorderStatus.Confirmed
                : anyFulfilled  ? PreorderStatus.PartiallyFulfilled
                : PreorderStatus.Pending;

            return new CustomerPreorderRow
            {
                PreorderId    = p.Id,
                OrderId       = p.OrderId,
                DateOfReceipt = p.DateOfReceipt,
                CreatedOnUtc  = p.CreatedOnUtc,
                Status        = effectiveStatus,
                CustomerNote  = p.CustomerNote,
                Items         = items.Select(i =>
                {
                    productById.TryGetValue(i.ProductId, out var dto);
                    return new CustomerPreorderItemRow
                    {
                        ProductName       = dto?.Name ?? $"Termék #{i.ProductId}",
                        IsMeasurable      = dto?.IsMeasurable ?? false,
                        RequestedQuantity = i.RequestedQuantity,
                        FulfilledQuantity = i.FulfilledQuantity,
                        UnitPriceInclTax  = i.UnitPriceInclTax,
                        Status            = i.FulfilledQuantity == 0
                            ? PreorderItemStatus.Pending
                            : i.FulfilledQuantity >= i.RequestedQuantity
                                ? PreorderItemStatus.Fulfilled
                                : PreorderItemStatus.PartiallyFulfilled
                    };
                }).ToList()
            };
        }).ToList();

        return View("~/Plugins/Misc.FruitBankPlugin/Views/CustomerPreorder/List.cshtml", rows);
    }

    // ── Inner models ──────────────────────────────────────────────────────────

    public class CustomerPreorderRow
    {
        public int                          PreorderId    { get; set; }
        public int?                         OrderId       { get; set; }
        public DateTime                     DateOfReceipt { get; set; }
        public DateTime                     CreatedOnUtc  { get; set; }
        public PreorderStatus               Status        { get; set; }
        public string?                      CustomerNote  { get; set; }
        public List<CustomerPreorderItemRow> Items        { get; set; } = new();
    }

    public class CustomerPreorderItemRow
    {
        public string            ProductName       { get; set; } = string.Empty;
        public bool              IsMeasurable      { get; set; }
        public int               RequestedQuantity { get; set; }
        public int               FulfilledQuantity { get; set; }
        public decimal           UnitPriceInclTax  { get; set; }
        public PreorderItemStatus Status           { get; set; }
    }
}
