from typing   import Optional
from loguru   import logger

from boot.config                  import CONFIG
from core.beans.enum.UploadStatus import UploadStatus
from core.beans.po.FilePO         import FilePO
from core.dao.MysqlRecord         import LiveOpRecord, IoTRecord
from core.dao.RabbitMQClient      import RabbitMQClient, VideoStreamInfo
from core.pattern.singleton       import singleton


@singleton
class DataCommitter:
  rabbit: Optional[RabbitMQClient]

  def __init__(self):
    self.rabbit = RabbitMQClient() if CONFIG.app.modules.light or CONFIG.app.modules.uavms else None

  def save_to_db(self, po: FilePO) -> bool:
    if CONFIG.app.modules.cmlc:
      r = LiveOpRecord(
        hub=po.app, stream=po.stream, type="ts", status=UploadStatus.SUCCESS,
        fileid=po.uuid, filename=po.relative_path, size=po.size,
        time_begin=po.begin, time_end=po.end
      ).save(force_insert=True)
      if r != 1:
        logger.error(f"Failed to save LiveOpRecord to DB: {po.filename}, ret: {r}.")
        return False

    if CONFIG.app.modules.uavms:
      r = IoTRecord(
        ts_file_name=po.relative_path, start_time=po.begin, end_time=po.end,
        file_size=po.size, device_id=po.stream_id, id=po.uuid,
        file_type="video", ref_id=po.ref_id, ext_json="{}",
        user_id=CONFIG.app.mysql.iot_default_biz_user, ai_object=None,
      ).save(force_insert=True)
      if r != 1:
        logger.error(f"Failed to save IoTRecord to DB: {po.filename}, ret: {r}.")
        return False

    if CONFIG.app.modules.light:
      start_timestamp = int(po.begin.timestamp() * 1000)
      end_timestamp   = int(  po.end.timestamp() * 1000)
      info = VideoStreamInfo(
        start_time=start_timestamp, duration=end_timestamp - start_timestamp,
        stream_id=po.stream_id, hub=po.app, stream=po.stream, file_id=po.uuid,
        md5=None, name=po.relative_path, type="ts", url=None,
        size=po.size, engine_type="zlm"
      )
      self.rabbit.send(info.to_json())

    return True

  @staticmethod
  def failed_to_sync_to_cloud_live(po: FilePO):
    (
      LiveOpRecord
     .update(status=UploadStatus.FAILED_TO_SYNC_TO_CLOUD_LIVE)
     .where(LiveOpRecord.fileid==po.uuid)
     .execute()
    )

