using CartWise.Application.Interfaces;
using CartWise.Infrastructure.Identity;
using CartWise.Web.ViewModels.Purchase;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;

namespace CartWise.Web.Controllers;

[Authorize]
[Route("purchases")]
public class PurchaseController : Controller
{
    private readonly IPurchaseService _purchaseService;
    private readonly IHouseholdService _householdService;
    private readonly UserManager<ApplicationUser> _userManager;

    public PurchaseController(IPurchaseService purchaseService, IHouseholdService householdService, UserManager<ApplicationUser> userManager)
    {
        _purchaseService = purchaseService;
        _householdService = householdService;
        _userManager = userManager;
    }

    [HttpGet("")]
    public async Task<IActionResult> Index()
    {
        var household = await CurrentHouseholdOrNullAsync();
        if (household is null)
        {
            return RedirectToAction("Create", "Household");
        }

        var purchases = await _purchaseService.GetHouseholdPurchasesAsync(household.HouseholdId);

        var viewModel = new PurchaseListViewModel
        {
            Purchases = purchases.Select(p => new PurchaseSummaryViewModel
            {
                PurchaseId = p.PurchaseId,
                PurchasedUtc = p.PurchasedUtc,
                IsCompleted = p.IsCompleted,
                Total = p.Total,
                ItemCount = p.Items.Count
            }).ToList()
        };

        return View(viewModel);
    }

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

        var result = await _purchaseService.StartPurchaseAsync(household.HouseholdId, userId, DateTime.UtcNow);
        if (!result.IsSuccess)
        {
            return RedirectToAction(nameof(Index));
        }

        return RedirectToAction(nameof(Details), new { id = result.Value!.PurchaseId });
    }

    [HttpGet("{id:guid}")]
    public async Task<IActionResult> Details(Guid id)
    {
        var household = await CurrentHouseholdOrNullAsync();
        if (household is null)
        {
            return RedirectToAction("Create", "Household");
        }

        var purchase = await _purchaseService.GetPurchaseAsync(household.HouseholdId, id);
        if (purchase is null)
        {
            return NotFound();
        }

        return View(ToViewModel(purchase));
    }

    [HttpPost("{id:guid}/items")]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> AddItem(Guid id, [Bind(Prefix = "NewItem")] AddPurchaseItemViewModel model)
    {
        var household = await CurrentHouseholdOrNullAsync();
        if (household is null)
        {
            return RedirectToAction("Create", "Household");
        }

        var purchase = await _purchaseService.GetPurchaseAsync(household.HouseholdId, id);
        if (purchase is null)
        {
            return NotFound();
        }

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

        var result = await _purchaseService.AddPurchaseItemAsync(household.HouseholdId, id, model.Description, model.LinePrice, model.Quantity, model.Unit);
        if (!result.IsSuccess)
        {
            ModelState.AddModelError(string.Empty, result.Error!);
            var viewModel = ToViewModel(purchase);
            viewModel.NewItem = model;
            return View(nameof(Details), viewModel);
        }

        return RedirectToAction(nameof(Details), new { id });
    }

    [HttpPost("{id:guid}/complete")]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> Complete(Guid id)
    {
        var household = await CurrentHouseholdOrNullAsync();
        if (household is null)
        {
            return RedirectToAction("Create", "Household");
        }

        await _purchaseService.CompletePurchaseAsync(household.HouseholdId, id);

        return RedirectToAction(nameof(Details), new { id });
    }

    private async Task<Domain.Entities.Household?> CurrentHouseholdOrNullAsync()
    {
        var userId = _userManager.GetUserId(User)!;
        return await _householdService.GetCurrentHouseholdAsync(userId);
    }

    private static PurchaseDetailsViewModel ToViewModel(Domain.Entities.Purchase purchase) => new()
    {
        PurchaseId = purchase.PurchaseId,
        PurchasedUtc = purchase.PurchasedUtc,
        IsCompleted = purchase.IsCompleted,
        Subtotal = purchase.Subtotal,
        Tax = purchase.Tax,
        Total = purchase.Total,
        Items = purchase.Items.Select(i => new PurchaseItemViewModel
        {
            Description = i.Description,
            Quantity = i.Quantity,
            Unit = i.Unit,
            LinePrice = i.LinePrice
        }).ToList()
    };
}
