#!/usr/bin/env python3
"""
🤖 Subscription Lifecycle Worker (Robot-20)
A 20-as Gitea kártya implementációja: Lejárt előfizetések automatikus kezelése.

Folyamat:
1. Lekérdezés: Azokat a User-eket, ahol subscription_expires_at < NOW() ÉS subscription_plan != 'FREE'
2. Downgrade: subscription_plan = "FREE", is_vip = False
3. Naplózás: Főkönyvi bejegyzés (SUBSCRIPTION_EXPIRED)
4. Értesítés: NotificationService küldése a downgrade-ről

Futtatás:
- Napi egyszer (cron) vagy manuálisan: docker exec sf_api python -m app.workers.system.subscription_worker
"""

import asyncio
import logging
from datetime import datetime, timezone
from typing import List

from sqlalchemy import select, update, and_
from sqlalchemy.ext.asyncio import AsyncSession

from app.database import AsyncSessionLocal
from app.models.identity import User
from app.models import FinancialLedger, LedgerEntryType, WalletType
from app.services.billing_engine import record_ledger_entry
from app.services.notification_service import NotificationService

logger = logging.getLogger("subscription-worker")

async def process_expired_subscriptions(db: AsyncSession) -> dict:
    """
    Atomikus tranzakcióban feldolgozza a lejárt előfizetéseket.
    
    Returns:
        dict: Statisztikák (processed_count, downgraded_users, errors)
    """
    now = datetime.now(timezone.utc)
    
    # 1. Lekérdezés: Lejárt előfizetések, amelyek még nem FREE-ek
    stmt = select(User).where(
        and_(
            User.subscription_expires_at < now,
            User.subscription_plan != 'FREE',
            User.is_deleted == False,
            User.is_active == True
        )
    ).with_for_update(skip_locked=True)  # Atomikus zárolás
    
    result = await db.execute(stmt)
    expired_users: List[User] = result.scalars().all()
    
    stats = {
        "processed_count": len(expired_users),
        "downgraded_users": [],
        "errors": []
    }
    
    for user in expired_users:
        try:
            # 2. Downgrade
            old_plan = user.subscription_plan
            user.subscription_plan = "FREE"
            user.is_vip = False
            # subscription_expires_at marad null vagy régi érték (lejárt)
            
            # 3. Főkönyvi bejegyzés (SUBSCRIPTION_EXPIRED)
            # Megjegyzés: amount = 0, mert nem történik pénzmozgás, csak naplózás
            ledger_entry = await record_ledger_entry(
                db=db,
                user_id=user.id,
                amount=0.0,
                entry_type=LedgerEntryType.DEBIT,
                wallet_type=WalletType.SYSTEM,
                transaction_type="SUBSCRIPTION_EXPIRED",
                description=f"Előfizetés lejárt: {old_plan} → FREE",
                reference_type="subscription",
                reference_id=user.id
            )
            
            # 4. Értesítés küldése
            await NotificationService.send_notification(
                db=db,
                user_id=user.id,
                title="Előfizetésed lejárt",
                message=f"A(z) {old_plan} előfizetésed lejárt, ezért átállítottuk a FREE csomagra. További előnyökért frissíts előfizetést!",
                category="billing",
                priority="medium",
                data={
                    "old_plan": old_plan,
                    "new_plan": "FREE",
                    "user_id": user.id,
                    "expired_at": user.subscription_expires_at.isoformat() if user.subscription_expires_at else None
                },
                send_email=True,
                email_template="subscription_expired",
                email_vars={
                    "recipient": user.email,
                    "first_name": user.person.first_name if user.person else "Partnerünk",
                    "old_plan": old_plan,
                    "new_plan": "FREE",
                    "lang": user.preferred_language
                }
            )
            
            stats["downgraded_users"].append({
                "user_id": user.id,
                "email": user.email,
                "old_plan": old_plan,
                "new_plan": "FREE"
            })
            
            logger.info(f"User {user.id} ({user.email}) subscription downgraded from {old_plan} to FREE")
            
        except Exception as e:
            logger.error(f"Error processing user {user.id}: {e}", exc_info=True)
            stats["errors"].append({"user_id": user.id, "error": str(e)})
    
    # Commit a tranzakció
    await db.commit()
    
    return stats

async def main():
    """Fő futtató függvény, amelyet a cron hív."""
    logger.info("Starting subscription worker...")
    
    async with AsyncSessionLocal() as db:
        try:
            stats = await process_expired_subscriptions(db)
            logger.info(f"Subscription worker completed. Stats: {stats}")
            print(f"✅ Subscription worker completed. Processed: {stats['processed_count']}, Downgraded: {len(stats['downgraded_users'])}")
        except Exception as e:
            logger.error(f"Subscription worker failed: {e}", exc_info=True)
            await db.rollback()
            raise

if __name__ == "__main__":
    asyncio.run(main())