import modal

from ..ffmpeg_app import ffmpeg_worker_image, app, config, s3_mount, local_copy_to_s3, output_path_prefix

with ffmpeg_worker_image.imports():
    from BowongModalFunctions.models.ffmpeg_worker_model import FFMpegSliceSegment
    from BowongModalFunctions.models.media_model import MediaSources, MediaProtocol, MediaSource
    from BowongModalFunctions.models.web_model import SentryTransactionInfo, WebhookNotify, FFMPEGResult
    from BowongModalFunctions.utils.PathUtils import FileUtils
    from BowongModalFunctions.utils.SentryUtils import SentryUtils
    from BowongModalFunctions.utils.VideoUtils import VideoUtils, FFMPEGSliceOptions
    import sentry_sdk
    from loguru import logger
    from typing import Optional, Tuple, List
    from modal import current_function_call_id


    @app.function(
        timeout=900,
        cloud="aws",
        cpu=(10, 64),
        max_containers=config.ffmpeg_slice_worker_concurrency,
        volumes={
            s3_mount: modal.CloudBucketMount(
                bucket_name=config.S3_bucket_name,
                secret=modal.Secret.from_name("aws-s3-secret",
                                              environment_name=config.modal_environment),
            ),
        },
    )
    @modal.concurrent(max_inputs=1)
    async def ffmpeg_slice_media(media: MediaSource,
                                 markers: List[FFMpegSliceSegment],
                                 options: FFMPEGSliceOptions,
                                 sentry_trace: Optional[SentryTransactionInfo] = None,
                                 webhook: Optional[WebhookNotify] = None) -> Tuple[
        List[FFMPEGResult], Optional[SentryTransactionInfo]]:
        fn_id = current_function_call_id()

        @SentryUtils.sentry_tracker(name="视频文件/直播切割任务", op="ffmpeg.slice.media", fn_id=fn_id,
                                    sentry_trace_id=sentry_trace.x_trace_id if sentry_trace else None,
                                    sentry_baggage=sentry_trace.x_baggage if sentry_trace else None)
        @SentryUtils.webhook_handler(webhook=webhook, func_id=fn_id)
        async def ffmpeg_slice_process(media_source: MediaSource, media_markers: List[FFMpegSliceSegment],
                                       fn_id: str, options: FFMPEGSliceOptions = None, is_streams: bool = False,
                                       ) -> List[FFMPEGResult]:
            if not is_streams:
                cache_filepath = f"{s3_mount}/{media_source.cache_filepath}"
                logger.info(f"从{media_source.urn}切割")
                for i, marker in enumerate(media_markers):
                    logger.info(f"[{i}] {marker.start.toFormatStr()} --> {marker.end.toFormatStr()}")
            else:
                cache_filepath = media_source.path


            segments = await VideoUtils.ffmpeg_slice_media(media_path=cache_filepath,
                                                           media_markers=media_markers,
                                                           options=options,
                                                           is_streams=is_streams,
                                                           output_path=f"{output_path_prefix}/{config.modal_environment}/slice/outputs/{fn_id}/output.mp4")
            return [FFMPEGResult(urn=local_copy_to_s3([segment[0]])[0], metadata=segment[1],
                                 content_length=FileUtils.get_file_size(segment[0])) for segment in segments]

        match media.protocol:
            case MediaProtocol.hls:
                outputs = await ffmpeg_slice_process(media_source=media,
                                                     media_markers=markers,
                                                     options=options,
                                                     is_streams=True,
                                                     fn_id=fn_id)
            case MediaProtocol.vod:
                outputs = await ffmpeg_slice_process(media_source=media,
                                                     media_markers=markers,
                                                     options=options,
                                                     is_streams=False,
                                                     fn_id=fn_id)
            case MediaProtocol.s3:
                outputs = await ffmpeg_slice_process(media_source=media,
                                                     media_markers=markers,
                                                     options=options,
                                                     is_streams=False,
                                                     fn_id=fn_id)
            case _:  # webhook不会报错，需要确认
                raise NotImplementedError("暂不支持的协议")

        return [result for result in outputs], sentry_trace
