from __future__ import annotations

from my_modules.app.setup import LIMITER
from my_modules.decoratory.header import token_required
from quart_common.web.wide_event import add_wide_event_context

from quart import Blueprint, abort, current_app, send_file

api_download_bp = Blueprint('api_download', __name__)

def _last_modified_from_file(file_data: dict):
  uploaded_at = file_data.get('uploaded_at')
  if uploaded_at is None:
    return None
  try:
    return int(uploaded_at) / 1000
  except (TypeError, ValueError):
    return None

@api_download_bp.get('/api/files/<path:file_id>/download')
@LIMITER.limit('60 per minute;1000 per hour;')
@token_required(['files', 'mesh'])
async def api_file_download(file_id: str, user: dict):
  add_wide_event_context(nanoshare={'operation': 'api_file_download', 'file_id': file_id})

  file_data = await current_app.convex.get_file_informations(file_id=file_id, user_id=user['sub'])
  if not file_data:
    add_wide_event_context(nanoshare={'operation_status': 'not_found'})
    abort(404)

  if file_data.get('expired'):
    add_wide_event_context(nanoshare={'operation_status': 'expired'})
    abort(410)

  storage_id = file_data.get('db_image_url')
  if not storage_id:
    add_wide_event_context(nanoshare={'operation_status': 'missing_storage'})
    abort(404)

  content_type = file_data.get('content_type') or 'application/octet-stream'
  file_name = file_data.get('file_name') or file_id
  add_wide_event_context(nanoshare={'operation_status': 'served', 'content_type': content_type})

  response = await send_file(
    filename_or_io=await current_app.convex.get_from_storage(storage_id),
    mimetype=content_type,
    as_attachment=True,
    attachment_filename=file_name,
    conditional=True,
    cache_timeout=0,
    last_modified=_last_modified_from_file(file_data),
  )
  response.headers['Cache-Control'] = 'private, no-store'
  return response
