using MongoDB.Driver;
using Nalu.Web.Data.Models;

namespace Nalu.Web.Data.Repositories;

public class UsageRepository(MongoDbContext db)
{
    /// <summary>
    /// Atomically increments daily and monthly counters.
    /// Returns (dailyCount, monthlyCount) AFTER increment.
    /// Returns null if MongoDB is not connected.
    /// </summary>
    public async Task<(int Daily, int Monthly)?> IncrementAsync(
        string apiKey, string plan, CancellationToken ct = default)
    {
        if (!db.IsConnected) return null;

        var now = DateTime.UtcNow;
        var date = now.ToString("yyyy-MM-dd");
        var yearMonth = now.ToString("yyyy-MM");

        // Upsert: if doc exists increment, else create with count=1
        var filter = Builders<UsageDaily>.Filter.And(
            Builders<UsageDaily>.Filter.Eq(u => u.ApiKey, apiKey),
            Builders<UsageDaily>.Filter.Eq(u => u.Date, date));

        var update = Builders<UsageDaily>.Update
            .Inc(u => u.DailyCount, 1)
            .Inc(u => u.MonthlyCount, 1)
            .SetOnInsert(u => u.Plan, plan)
            .SetOnInsert(u => u.YearMonth, yearMonth);

        var options = new FindOneAndUpdateOptions<UsageDaily>
        {
            IsUpsert = true,
            ReturnDocument = ReturnDocument.After
        };

        var doc = await db.UsageDaily.FindOneAndUpdateAsync(filter, update, options, ct);
        return (doc.DailyCount, doc.MonthlyCount);
    }

    /// <summary>
    /// Returns (dailyCount, monthlyCount) for the current period without modifying.
    /// </summary>
    public async Task<(int Daily, int Monthly)> GetCurrentUsageAsync(
        string apiKey, CancellationToken ct = default)
    {
        if (!db.IsConnected) return (0, 0);

        var now = DateTime.UtcNow;
        var date = now.ToString("yyyy-MM-dd");
        var yearMonth = now.ToString("yyyy-MM");

        var doc = await db.UsageDaily
            .Find(u => u.ApiKey == apiKey && u.Date == date)
            .FirstOrDefaultAsync(ct);

        if (doc is null) return (0, 0);

        // Sum all docs in current month for monthly total
        var monthlyDocs = await db.UsageDaily
            .Find(u => u.ApiKey == apiKey && u.YearMonth == yearMonth)
            .ToListAsync(ct);

        return (doc.DailyCount, monthlyDocs.Sum(d => d.DailyCount));
    }
}
