using Microsoft.EntityFrameworkCore;
using MiningService.Domain.AggregatesModel.ConfigurationAggregate;
using MiningService.Domain.SeedWork;

namespace MiningService.Infrastructure.Repositories;

/// <summary>
/// EN: In-memory repository for Configuration aggregates with database fallback.
/// VI: Repository in-memory cho Configuration aggregates với fallback database.
/// </summary>
public class ConfigurationRepository : IConfigurationRepository
{
    private readonly MiningServiceContext _context;
    private static MiningConfiguration? _miningConfig;
    private static StreakConfiguration? _streakConfig;
    private static ReferralConfiguration? _referralConfig;
    private static readonly object _lock = new();

    public IUnitOfWork UnitOfWork => _context;

    public ConfigurationRepository(MiningServiceContext context)
    {
        _context = context ?? throw new ArgumentNullException(nameof(context));
    }

    public async Task<MiningConfiguration> GetMiningConfigAsync(CancellationToken cancellationToken = default)
    {
        if (_miningConfig != null)
            return _miningConfig;

        lock (_lock)
        {
            _miningConfig ??= MiningConfiguration.CreateDefault();
        }

        // Try to load from database in the future
        // var dbConfig = await _context.MiningConfigurations.FirstOrDefaultAsync(cancellationToken);
        // if (dbConfig != null) _miningConfig = dbConfig;

        return _miningConfig;
    }

    public async Task<StreakConfiguration> GetStreakConfigAsync(CancellationToken cancellationToken = default)
    {
        if (_streakConfig != null)
            return _streakConfig;

        lock (_lock)
        {
            _streakConfig ??= StreakConfiguration.CreateDefault();
        }

        return await Task.FromResult(_streakConfig);
    }

    public async Task<ReferralConfiguration> GetReferralConfigAsync(CancellationToken cancellationToken = default)
    {
        if (_referralConfig != null)
            return _referralConfig;

        lock (_lock)
        {
            _referralConfig ??= ReferralConfiguration.CreateDefault();
        }

        return await Task.FromResult(_referralConfig);
    }

    public void UpdateMiningConfig(MiningConfiguration config)
    {
        lock (_lock)
        {
            _miningConfig = config;
        }
    }

    public void UpdateStreakConfig(StreakConfiguration config)
    {
        lock (_lock)
        {
            _streakConfig = config;
        }
    }

    public void UpdateReferralConfig(ReferralConfiguration config)
    {
        lock (_lock)
        {
            _referralConfig = config;
        }
    }
}
