"""
Аналитика чата и экспорт данных
"""
import json
import logging
from datetime import datetime, timedelta
from typing import Dict, List, Any
from pathlib import Path
from sqlalchemy import select, func, distinct
from sqlalchemy.ext.asyncio import AsyncSession
from database.models import User, Message
from config import EXPORT_DIR

logger = logging.getLogger(__name__)


class ChatAnalytics:
    """Аналитика чата"""
    
    def __init__(self, session: AsyncSession):
        self.session = session
        self.export_dir = Path(EXPORT_DIR)
        self.export_dir.mkdir(parents=True, exist_ok=True)
    
    async def get_general_stats(self) -> Dict[str, Any]:
        """Общая статистика чата"""
        # Всего пользователей
        stmt = select(func.count(User.user_id))
        result = await self.session.execute(stmt)
        total_users = result.scalar() or 0
        
        # Верифицированы
        stmt = select(func.count(User.user_id)).where(User.verified == True)
        result = await self.session.execute(stmt)
        verified_users = result.scalar() or 0
        
        # Сообщения всего
        stmt = select(func.count(Message.id))
        result = await self.session.execute(stmt)
        total_messages = result.scalar() or 0
        
        # Сообщения за неделю
        week_ago = datetime.utcnow() - timedelta(days=7)
        stmt = (
            select(func.count(Message.id))
            .where(Message.timestamp >= week_ago)
        )
        result = await self.session.execute(stmt)
        messages_week = result.scalar() or 0
        
        # Сообщения за день
        day_ago = datetime.utcnow() - timedelta(days=1)
        stmt = (
            select(func.count(Message.id))
            .where(Message.timestamp >= day_ago)
        )
        result = await self.session.execute(stmt)
        messages_day = result.scalar() or 0
        
        # Подозрительные
        stmt = (
            select(func.count(User.user_id))
            .where(User.spy_score >= 31)
            .where(User.spy_score <= 60)
        )
        result = await self.session.execute(stmt)
        suspicious_count = result.scalar() or 0
        
        # Шпионы
        stmt = (
            select(func.count(User.user_id))
            .where(User.spy_score > 60)
        )
        result = await self.session.execute(stmt)
        spies_count = result.scalar() or 0
        
        # Топ пользователей за неделю
        top_users = await self._get_top_users(week_ago, limit=5)
        
        return {
            'total_users': total_users,
            'verified_users': verified_users,
            'unverified_users': total_users - verified_users,
            'total_messages': total_messages,
            'messages_week': messages_week,
            'messages_day': messages_day,
            'suspicious_count': suspicious_count,
            'spies_count': spies_count,
            'top_users': top_users,
        }
    
    async def _get_top_users(self, since: datetime, limit: int = 5) -> str:
        """Топ пользователей по активности"""
        stmt = (
            select(User.user_id, User.first_name, func.count(Message.id).label('count'))
            .join(Message, User.user_id == Message.user_id)
            .where(Message.timestamp >= since)
            .group_by(User.user_id, User.first_name)
            .order_by(func.count(Message.id).desc())
            .limit(limit)
        )
        result = await self.session.execute(stmt)
        rows = result.all()
        
        if not rows:
            return 'нет данных'
        
        lines = []
        for i, (user_id, name, count) in enumerate(rows, 1):
            display_name = name or f'user{user_id}'
            lines.append(f'{i}. {display_name}: {count}')
        
        return ', '.join(lines)
    
    async def export_to_json(self) -> str:
        """
        Экспорт данных чата в JSON
        Возвращает путь к файлу
        """
        timestamp = datetime.utcnow().strftime('%Y%m%d_%H%M%S')
        filename = f'chat_export_{timestamp}.json'
        filepath = self.export_dir / filename
        
        # Получаем всех пользователей
        stmt = select(User).order_by(User.join_date.desc())
        result = await self.session.execute(stmt)
        users = list(result.scalars().all())
        
        # Получаем сообщения за последнюю неделю
        week_ago = datetime.utcnow() - timedelta(days=7)
        stmt = (
            select(Message)
            .where(Message.timestamp >= week_ago)
            .order_by(Message.timestamp.desc())
            .limit(10000)  # Ограничение на количество
        )
        result = await self.session.execute(stmt)
        messages = list(result.scalars().all())
        
        # Формируем экспорт
        export_data = {
            'export_date': datetime.utcnow().isoformat(),
            'chat_id': None,  # Заполнится при использовании
            'period': {
                'from': week_ago.isoformat(),
                'to': datetime.utcnow().isoformat(),
            },
            'summary': {
                'total_users': len(users),
                'verified_users': sum(1 for u in users if u.verified),
                'total_messages': len(messages),
            },
            'users': [
                {
                    'user_id': u.user_id,
                    'username': u.username,
                    'first_name': u.first_name,
                    'last_name': u.last_name,
                    'apartment': u.apartment,
                    'verified': u.verified,
                    'join_date': u.join_date.isoformat() if u.join_date else None,
                    'message_count': u.message_count,
                    'spy_score': u.spy_score,
                    'spy_flags': json.loads(u.spy_flags) if u.spy_flags else [],
                }
                for u in users
            ],
            'messages': [
                {
                    'message_id': m.message_id,
                    'user_id': m.user_id,
                    'text': m.text[:500] if m.text else None,  # Обрезаем длинные
                    'timestamp': m.timestamp.isoformat() if m.timestamp else None,
                    'reply_to': m.reply_to_message_id,
                }
                for m in messages
            ]
        }
        
        # Сохраняем
        with open(filepath, 'w', encoding='utf-8') as f:
            json.dump(export_data, f, ensure_ascii=False, indent=2)
        
        logger.info(f'Экспорт сохранён: {filepath}')
        return str(filepath)
    
    async def get_activity_report(self, days: int = 7) -> Dict[str, Any]:
        """Отчёт по активности за период"""
        since = datetime.utcnow() - timedelta(days=days)
        
        # Активные пользователи
        stmt = (
            select(distinct(Message.user_id))
            .where(Message.timestamp >= since)
        )
        result = await self.session.execute(stmt)
        active_users = len(list(result.scalars().all()))
        
        # Самые активные часы
        stmt = (
            select(
                func.strftime('%H', Message.timestamp).label('hour'),
                func.count().label('count')
            )
            .where(Message.timestamp >= since)
            .group_by(func.strftime('%H', Message.timestamp))
            .order_by(func.count().desc())
            .limit(5)
        )
        result = await self.session.execute(stmt)
        peak_hours = [(row.hour, row.count) for row in result.all()]
        
        return {
            'active_users': active_users,
            'peak_hours': peak_hours,
            'period_days': days,
        }
