using System.Globalization;
using CartWise.Application.Interfaces;
using CartWise.Infrastructure.Identity;
using CartWise.Web.ViewModels.ShoppingList;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;

namespace CartWise.Web.Controllers;

[Authorize]
[Route("list")]
public class ShoppingListController : Controller
{
    private readonly IShoppingListService _shoppingListService;
    private readonly IHouseholdService _householdService;
    private readonly UserManager<ApplicationUser> _userManager;

    public ShoppingListController(
        IShoppingListService shoppingListService,
        IHouseholdService householdService,
        UserManager<ApplicationUser> userManager)
    {
        _shoppingListService = shoppingListService;
        _householdService = householdService;
        _userManager = userManager;
    }

    [HttpGet("")]
    public async Task<IActionResult> Index()
    {
        var userId = _userManager.GetUserId(User)!;
        var household = await _householdService.GetCurrentHouseholdAsync(userId);
        if (household is null)
        {
            return RedirectToAction("Create", "Household");
        }

        var list = await GetOrCreateActiveListAsync(household.HouseholdId, userId);
        return View(ToViewModel(list));
    }

    [HttpPost("items")]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> AddItem([Bind(Prefix = "NewItem")] AddShoppingListItemViewModel model)
    {
        var userId = _userManager.GetUserId(User)!;
        var household = await _householdService.GetCurrentHouseholdAsync(userId);
        if (household is null)
        {
            return RedirectToAction("Create", "Household");
        }

        var list = await GetOrCreateActiveListAsync(household.HouseholdId, userId);

        if (!ModelState.IsValid)
        {
            var viewModel = ToViewModel(list);
            viewModel.NewItem = model;
            return View(nameof(Index), viewModel);
        }

        var result = await _shoppingListService.AddItemAsync(list.ShoppingListId, model.DisplayName, model.Quantity, model.Unit, userId);
        if (!result.IsSuccess)
        {
            ModelState.AddModelError(string.Empty, result.Error!);
            var viewModel = ToViewModel(list);
            viewModel.NewItem = model;
            return View(nameof(Index), viewModel);
        }

        return RedirectToAction(nameof(Index));
    }

    private async Task<Domain.Entities.ShoppingList> GetOrCreateActiveListAsync(Guid householdId, string userId)
    {
        var list = await _shoppingListService.GetActiveListAsync(householdId);
        if (list is not null)
        {
            return list;
        }

        var createResult = await _shoppingListService.CreateListAsync(householdId, "Groceries", userId);
        return createResult.Value ?? await _shoppingListService.GetActiveListAsync(householdId)
            ?? throw new InvalidOperationException("Unable to resolve the household's active shopping list.");
    }

    private static ShoppingListViewModel ToViewModel(Domain.Entities.ShoppingList list) => new()
    {
        ShoppingListId = list.ShoppingListId,
        Name = list.Name,
        Items = list.Items
            .OrderBy(i => i.SortOrder)
            .Select(i => new ShoppingListItemViewModel
            {
                Id = i.ShoppingListItemId,
                DisplayName = i.DisplayName,
                QuantityDisplay = FormatQuantity(i.Quantity, i.Unit),
                Status = i.Status,
                ConcurrencyToken = i.RowVersion
            })
            .ToList()
    };

    private static string? FormatQuantity(decimal? quantity, string? unit)
    {
        if (quantity is null)
        {
            return unit;
        }

        var quantityText = quantity.Value.ToString("0.###", CultureInfo.InvariantCulture);
        return unit is null ? quantityText : $"{quantityText} {unit}";
    }
}
