using Microsoft.EntityFrameworkCore;
using DramaLing.Api.Data;
using DramaLing.Api.Models.Entities;

namespace DramaLing.Api.Repositories;

/// <summary>
/// User Repository 實作
/// </summary>
public class UserRepository : BaseRepository<User>, IUserRepository
{
    public UserRepository(DramaLingDbContext context, ILogger<UserRepository> logger)
        : base(context, logger)
    {
    }

    #region 用戶查詢

    public async Task<User?> GetByEmailAsync(string email)
    {
        try
        {
            return await _dbSet
                .AsNoTracking()
                .FirstOrDefaultAsync(u => u.Email == email);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error getting user by email: {Email}", email);
            throw;
        }
    }

    public async Task<User?> GetByUsernameAsync(string username)
    {
        try
        {
            return await _dbSet
                .AsNoTracking()
                .FirstOrDefaultAsync(u => u.Username == username);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error getting user by username: {Username}", username);
            throw;
        }
    }

    public async Task<bool> ExistsByEmailAsync(string email)
    {
        try
        {
            return await _dbSet.AnyAsync(u => u.Email == email);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error checking user existence by email: {Email}", email);
            throw;
        }
    }

    public async Task<bool> ExistsByUsernameAsync(string username)
    {
        try
        {
            return await _dbSet.AnyAsync(u => u.Username == username);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error checking user existence by username: {Username}", username);
            throw;
        }
    }

    #endregion

    #region 用戶設定相關

    public async Task<User?> GetUserWithSettingsAsync(Guid userId)
    {
        try
        {
            return await _dbSet
                .AsNoTracking()
                .Include(u => u.Settings)
                .FirstOrDefaultAsync(u => u.Id == userId);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error getting user with settings: {UserId}", userId);
            throw;
        }
    }

    public async Task<User?> GetUserWithStatsAsync(Guid userId)
    {
        try
        {
            return await _dbSet
                .AsNoTracking()
                .Include(u => u.DailyStats!)
                .FirstOrDefaultAsync(u => u.Id == userId);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error getting user with stats: {UserId}", userId);
            throw;
        }
    }

    #endregion

    #region 學習進度統計

    public Task<Dictionary<string, object>> GetUserLearningStatsAsync(Guid userId)
    {
        try
        {
            var stats = new Dictionary<string, object>
            {
                ["TotalFlashcards"] = 0,
                ["MasteredFlashcards"] = 0,
                ["MasteryRate"] = 0.0,
                ["StudyDaysThisMonth"] = 0,
                ["TotalStudyTimeSeconds"] = 0
            };

            return Task.FromResult(stats);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error getting user learning stats: {UserId}", userId);
            throw;
        }
    }

    public Task<int> GetTotalStudyTimeAsync(Guid userId)
    {
        try
        {
            return Task.FromResult(0);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error getting total study time: {UserId}", userId);
            throw;
        }
    }

    public Task<DateTime?> GetLastActivityDateAsync(Guid userId)
    {
        try
        {
            return Task.FromResult<DateTime?>(DateTime.UtcNow);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error getting last activity date: {UserId}", userId);
            throw;
        }
    }

    #endregion

    #region 用戶活躍度

    public async Task<IEnumerable<User>> GetActiveUsersAsync(int days)
    {
        try
        {
            return await _dbSet
                .AsNoTracking()
                .Take(10) // 簡化實作
                .ToListAsync();
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error getting active users for {Days} days", days);
            throw;
        }
    }

    public async Task<IEnumerable<User>> GetNewUsersAsync(DateTime since)
    {
        try
        {
            return await _dbSet
                .AsNoTracking()
                .Where(u => u.CreatedAt >= since)
                .OrderByDescending(u => u.CreatedAt)
                .ToListAsync();
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error getting new users since: {Since}", since);
            throw;
        }
    }

    #endregion
}