using Managing.Application.Abstractions.Repositories;
using Managing.Application.Abstractions.Services;
using Managing.Domain.Accounts;
using Microsoft.EntityFrameworkCore;

namespace Managing.Infrastructure.Databases.PostgreSql;

public class PostgreSqlAccountRepository : IAccountRepository
{
    private readonly ManagingDbContext _context;
    private readonly ICacheService _cacheService;

    public PostgreSqlAccountRepository(ManagingDbContext context, ICacheService cacheService)
    {
        _context = context;
        _cacheService = cacheService;
    }



    public void DeleteAccountByName(string name)
    {
        var accountEntity = _context.Accounts
            .AsTracking() // Explicitly enable tracking for delete operations
            .FirstOrDefault(a => a.Name == name);
        if (accountEntity != null)
        {
            _context.Accounts.Remove(accountEntity);
            _context.SaveChanges();
        }
    }

    public async Task<Account> GetAccountByKeyAsync(string key)
    {
        try
        {
            await PostgreSqlConnectionHelper.EnsureConnectionOpenAsync(_context);

            var accountEntity = await _context.Accounts
                .AsNoTracking()
                .Include(a => a.User)
                .FirstOrDefaultAsync(a => a.Key == key)
                .ConfigureAwait(false);

            return PostgreSqlMappers.Map(accountEntity);
        }
        finally
        {
            // Always ensure the connection is closed after the operation
            await PostgreSqlConnectionHelper.SafeCloseConnectionAsync(_context);
        }
    }

    public async Task<Account> GetAccountByNameAsync(string name)
    {
        try
        {
            var cacheKey = $"account_{name}";
            var cachedAccount = _cacheService.GetValue<Account>(cacheKey);
            if (cachedAccount != null)
            {
                return cachedAccount;
            }

            var accountEntity = await _context.Accounts
                .AsNoTracking()
                .Include(a => a.User)
                .FirstOrDefaultAsync(a => a.Name == name)
                .ConfigureAwait(false);

            var account = PostgreSqlMappers.Map(accountEntity);
            _cacheService.SaveValue(cacheKey, account, TimeSpan.FromHours(1));
            return account;
        }
        catch (Exception ex)
        {
            // If there's an error, try to reset the connection
            throw;
        }
        finally
        {
        }
    }

    public async Task<IEnumerable<Account>> GetAccountsAsync()
    {
        try
        {
            await PostgreSqlConnectionHelper.EnsureConnectionOpenAsync(_context);

            // Use proper async operations with AsNoTracking for optimal performance
            var accountEntities = await _context.Accounts
                .AsNoTracking()
                .Include(a => a.User)
                .ToListAsync()
                .ConfigureAwait(false);

            return PostgreSqlMappers.Map(accountEntities);
        }
        finally
        {
            // Always ensure the connection is closed after the operation
            await PostgreSqlConnectionHelper.SafeCloseConnectionAsync(_context);
        }
    }

    public async Task InsertAccountAsync(Account account)
    {
        var accountEntity = PostgreSqlMappers.Map(account);

        // Handle User relationship - user should always have an ID at this point
        if (account.User == null)
        {
            throw new Exception($"Cannot create account {account.Name} without a user");
        }

        _context.Accounts.Add(accountEntity);
        await _context.SaveChangesAsync().ConfigureAwait(false);
    }
}