import logging from aiogram import Router, F, types from typing import Optional, Dict from datetime import datetime from config.settings import Settings from db.database import get_user_count_stats, get_payment_logs, get_message_logs_db, get_last_sync_status from bot.keyboards.inline.admin_keyboards import get_back_to_admin_panel_keyboard from bot.middlewares.i18n import JsonI18n router = Router(name="admin_statistics_router") async def show_statistics_handler(callback: types.CallbackQuery, i18n_data: dict, settings: Settings): current_lang = i18n_data.get("current_language", getattr(settings, 'DEFAULT_LANGUAGE', 'en')) i18n: Optional[JsonI18n] = i18n_data.get("i18n_instance") if not i18n: logging.error("i18n missing in show_statistics_handler") await callback.answer("Language service error.", show_alert=True) return _ = lambda key, **kwargs: i18n.gettext(current_lang, key, **kwargs) await callback.answer() stats_text_parts = [f"{_('admin_stats_header')}"] user_stats = await get_user_count_stats() stats_text_parts.append( _("admin_stats_users", total_users=user_stats.get("total_users", 0), banned_users=user_stats.get("banned_users", 0), active_subs=user_stats.get("users_with_active_subscriptions", 0))) last_payments = await get_payment_logs(limit=5) if last_payments: stats_text_parts.append( f"\n{_('admin_stats_recent_payments_header')}") for payment in last_payments: status_emoji = "✅" if payment['status'] == 'succeeded' else ( "⏳" if payment['status'] == 'pending' else "❌") user_info = f"User {payment['user_id']}" + ( f" (@{payment['username']})" if payment['username'] else "") payment_date_str = payment['created_at'] if isinstance(payment_date_str, str) and len(payment_date_str) > 10: payment_date_str = payment_date_str[:10] stats_text_parts.append( _("admin_stats_payment_item", status_emoji=status_emoji, amount=payment['amount'], currency=payment['currency'], user_info=user_info, p_status=payment['status'], p_date=payment_date_str)) else: stats_text_parts.append(f"\n{_('admin_stats_no_payments_found')}") sync_status = await get_last_sync_status() if sync_status: stats_text_parts.append( f"\n{_('admin_stats_last_sync_header')}") sync_time_val = sync_status['last_sync_time'] sync_time_str = "N/A" if isinstance(sync_time_val, datetime): sync_time_str = sync_time_val.strftime('%Y-%m-%d %H:%M:%S UTC') elif isinstance(sync_time_val, str): sync_time_str = sync_time_val[:19] if len( sync_time_val) > 19 else sync_time_val details_val = sync_status['details'] details_str = (details_val[:100] + "...") if details_val and len(details_val) > 100 else ( details_val or "N/A") stats_text_parts.append( f" {_('admin_stats_sync_time')}: {sync_time_str}") stats_text_parts.append( f" {_('admin_stats_sync_status')}: {sync_status['status']}") stats_text_parts.append( f" {_('admin_stats_sync_users_processed')}: {sync_status['users_processed_from_panel']}" ) stats_text_parts.append( f" {_('admin_stats_sync_subs_synced')}: {sync_status['subscriptions_synced']}" ) stats_text_parts.append( f" {_('admin_stats_sync_details_label')}: {details_str}") else: stats_text_parts.append(f"\n{_('admin_sync_status_never_run')}") final_text = "\n".join(stats_text_parts) if callback.message: try: await callback.message.edit_text( final_text, reply_markup=get_back_to_admin_panel_keyboard( current_lang, i18n), parse_mode="HTML") except Exception as e: logging.error(f"Error editing message for statistics: {e}", exc_info=True) for chunk in [ final_text[i:i + 4000] for i in range(0, len(final_text), 4000) ]: await callback.message.answer( chunk, reply_markup=get_back_to_admin_panel_keyboard( current_lang, i18n) if chunk == final_text[-len(chunk):] else None, parse_mode="HTML") else: logging.error("Cannot send statistics, callback.message is None.")