from my_helpers.db.convex.ConvexDbBase import ConvexDbBase
from my_helpers.db.convex.ConvexRuntime import ConvexRuntime

from my_modules.app.logger import logger

from datetime import datetime

class ConvexDB(ConvexDbBase):
  service_namespace = 'nanoshare'

  def __init__(self, runtime:ConvexRuntime):
    super().__init__(
      runtime=runtime,
      service=ConvexDB.service_namespace
    )

  # File Quary Functions
  async def get_file(self, file_id:str):
    data = await self.run_query(
      name='files:getByFileId',
      args={ 'file_id': file_id }
    )
    return data

  async def get_files(self, user_id:str):
    data = await self.run_query(
      name='files:getAllNotExpired',
      args={ 'user_id': user_id }
    )
    return [ {
      "file_id": x['file_id'],
      "file_name": x['file_name'],
      "file_path": x.get('file_path', ''),
      "file_size": x['file_size'],
      "note": x['note'],
      "expires_at": int(x['expires_at']) if x.get('expires_at', None) else '',
      "uploaded_at": int(x['uploaded_at']),
    } for x in data ]

  async def add_file(self, file_name:str, file_size:str, note:str, content_type:str, expires_at:datetime|None, storage_id:str, user_id:str, file_path:str=''):
    args = {
      'file_name': file_name, 'file_path': file_path, 'file_size': file_size, 'content_type': content_type,
      'note': note,
      'file_storage_id': storage_id, 'user_id': user_id
    }
    if expires_at:
      args['expires_at'] = expires_at.isoformat()

    data = await self.run_mutation(
      name='files:addNewFile',
      args=args,
    )
    return data

  async def update_file(self, file_id:str, file_name:str, note:str|None, expires_at:datetime|None, user_id:str, file_path:str='', preserve_missing:bool=False):
    args = {
      'file_id': file_id,
      'file_name': file_name,
      'file_path': file_path,
      'user_id': user_id
    }
    if note is not None:
      args['note'] = note
    elif not preserve_missing:
      args['note'] = ''
    if expires_at:
      args['expires_at'] = expires_at.isoformat()

    await self.run_mutation(
      name='files:updateFile',
      args=args,
    )

  async def delete_file(self, file_id:str, user_id:str):
    await self.run_mutation(
      name='files:deleteFile',
      args={ 'file_id': file_id, 'user_id': user_id }
    )

  async def get_file_informations(self, file_id:str, user_id:str):
    data = await self.run_query(
      name='files:getFileByIdAndUser',
      args={ 'file_id': file_id, 'user_id': user_id }
    )
    return data

  # File Access Quary Functions
  async def add_file_access(self, file_id: str, ip_address:str, status:str, user_agent:str):
    data = await self.run_mutation(
      name='access:addNewAccess',
      args={ 'file_id': file_id, 'ip_address': ip_address, 'user_agent': str(user_agent), 'status': status }
    )
    return data

  async def get_all_access(self, user_id:str):
    data = await self.run_query(
      name='access:getAllByUser',
      args={ 'user_id': user_id }
    )
    return data

  async def get_file_access(self, file_id:str, user_id:str):
    return []

    data = await self.run_query_with_reconnection(
      self.client.query_single,
      """
      SELECT files {
        accesses: {
          status,
          ip: { value },
          user_agent: { value },
          at
        }
      }
      FILTER .file_id = <str>$file_id
      LIMIT 1
      """,
      file_id=file_id,
    )

    if data:
      return [{
        "status": str(access.status),
        "ip": access.ip.value if access.ip else None,
        "user_agent": access.user_agent.value if access.user_agent else None,
        "accessed_at": access.at,
      } for access in data.accesses]
    return None
