from __future__ import annotations

import asyncio
import json

from my_modules.app.setup import LIMITER
from my_modules.decoratory.header import token_required
from quart import Blueprint, Response, current_app, stream_with_context

api_events_bp = Blueprint('api_events', __name__)

async def _snapshot(user_id: str) -> str:
  files = await current_app.convex.get_files(user_id)
  rows = []
  for item in files or []:
    if not isinstance(item, dict):
      continue
    rows.append({
      'file_id': item.get('file_id'),
      'file_name': item.get('file_name'),
      'file_path': item.get('file_path') or '',
      'file_size': item.get('file_size'),
      'expires_at': item.get('expires_at'),
      'updated_at': item.get('updated_at') or item.get('uploaded_at'),
    })
  rows.sort(key=lambda row: str(row.get('file_id') or ''))
  return json.dumps(rows, sort_keys=True, separators=(',', ':'))

@api_events_bp.get('/api/files/events')
@LIMITER.limit('6 per minute;60 per hour;')
@token_required(['files', 'mesh'])
async def api_file_events(user: dict):
  user_id = user['sub']

  @stream_with_context
  async def stream():
    previous = await _snapshot(user_id)
    yield 'event: ready\ndata: {}\n\n'
    while True:
      await asyncio.sleep(15)
      current = await _snapshot(user_id)
      if current != previous:
        previous = current
        yield f'event: files.changed\ndata: {current}\n\n'
      else:
        yield ': keepalive\n\n'

  response = Response(stream(), content_type='text/event-stream', headers={
    'Cache-Control': 'no-cache',
    'X-Accel-Buffering': 'no',
  })
  response.timeout = None
  return response
