using CartWise.Application.Interfaces;
using CartWise.Application.Results;
using CartWise.Domain.Entities;
using Microsoft.EntityFrameworkCore;

namespace CartWise.Application.Services;

public class HouseholdService : IHouseholdService
{
    private readonly IApplicationDbContext _db;
    private readonly TimeProvider _timeProvider;

    public HouseholdService(IApplicationDbContext db, TimeProvider timeProvider)
    {
        _db = db;
        _timeProvider = timeProvider;
    }

    public async Task<Result<Household>> CreateHouseholdAsync(string name, string userId, CancellationToken cancellationToken = default)
    {
        var alreadyBelongsToAHousehold = await _db.HouseholdMembers
            .AsNoTracking()
            .AnyAsync(m => m.UserId == userId, cancellationToken);

        if (alreadyBelongsToAHousehold)
        {
            return Result<Household>.Failure("You already belong to a household.");
        }

        Household household;
        try
        {
            household = new Household(name, userId, _timeProvider.GetUtcNow().UtcDateTime);
        }
        catch (ArgumentException ex)
        {
            return Result<Household>.Failure(ex.Message);
        }

        _db.Households.Add(household);
        await _db.SaveChangesAsync(cancellationToken);

        return Result<Household>.Success(household);
    }

    public async Task<Household?> GetCurrentHouseholdAsync(string userId, CancellationToken cancellationToken = default)
    {
        var householdId = await _db.HouseholdMembers
            .AsNoTracking()
            .Where(m => m.UserId == userId)
            .Select(m => m.HouseholdId)
            .FirstOrDefaultAsync(cancellationToken);

        if (householdId == Guid.Empty)
        {
            return null;
        }

        return await _db.Households
            .Include(h => h.Members)
            .AsNoTracking()
            .FirstOrDefaultAsync(h => h.HouseholdId == householdId, cancellationToken);
    }

    public async Task<bool> IsMemberAsync(Guid householdId, string userId, CancellationToken cancellationToken = default)
    {
        return await _db.HouseholdMembers
            .AsNoTracking()
            .AnyAsync(m => m.HouseholdId == householdId && m.UserId == userId, cancellationToken);
    }
}
