from .imports import *
from .pipeline_utils import *
class VideoPipeline:
    def __init__(self,*args,**kwargs):
        video_url,video_id,video_path,info,video_dir = get_video_url_path_from_args(*args,**kwargs)
        # 1) Normalize inputs
        self.video_url = video_url
        self.video_path = video_path
        self.video_id = video_id
        self.video_dir = video_dir
        self.force_refresh = kwargs.get('force_refresh')
        self.hide_audio = kwargs.get('hide_audio')
        self.registry = infoRegistry()
        self._video_context = {
            "url": self.video_url,
            "video_id": self.video_id,
            "video_path": self.video_path,
            "video_dir": self.video_dir,
            "force_refresh":self.force_refresh,
            "hide_audio":self.hide_audio,
        }
        logger.info(f"info == {self._video_context}")
        self.info = self.registry.get_video_info(**self._video_context)
        self.video_info = self.info.get("info") or {}
        self._video_context["registry"] = self.registry
        self._video_context["info"] = self.info
        self._video_context["video_info"] = self.video_info
        ctx = self._video_context

    def get_video_info(self):
        logger.info(f"""calling get_video_info from pipeline.py @ line 62 with url={self.video_url},
            video_id={self.video_id}
            video_path={self.video_path},
            registry={self.registry}""")
        return self.video_info or self.registry.get_video_info(**self._video_context,registry=self.registry,download_video=False)
        
    def download_video(self):
        return VideoDownloader(**self._video_context)
    
    def get_file_path(self, key: str):
        """
        Safely fetch a path from self.video_info and tell whether it exists on disk.
        """
        path = self.video_info.get(key)
        if not path:
            logger.info(f"{key} is empty or missing in video_info")
            return None, False

        exists = os.path.isfile(path)
        isexist = "exists" if exists else "does not exist"
        logger.info(f"{key} is {path} and {isexist}")
        return path, exists
    # === CAPTIONS ===
    def get_rawdata(self):
        # 1️⃣ Read from DB first
        record = get_video_record(**self._video_context) or {}
        rawdata = record.get("rawdata")
        if rawdata:
            return rawdata

        # 2️⃣ Fetch raw yt-dlp info directly (NO registry resolver)
        if not self.video_url:
            raise RuntimeError(
                f"get_rawdata: no video_url available for video_id={self.video_id}"
            )

        logger.info(
            f"Fetching rawdata via yt-dlp for video_id={self.video_id} url={self.video_url}"
        )

        rawdata = get_yt_dlp_info(self.video_url)

        if not isinstance(rawdata, dict):
            raise RuntimeError(
                f"yt-dlp returned invalid rawdata for video_id={self.video_id}"
            )

        # 3️⃣ Persist
        upsert_video(self.video_id, rawdata=rawdata)

        return rawdata
    # === AUDIO ===
    def ensure_audio(self):
        record = get_video_record(**self._video_context) or {}

        audio_path, exists = self.get_file_path("audio_path")
        if record and audio_path and exists:
            audio_format = audio_path.split(".")[-1]
            return audio_path, audio_format

        # Need to (re)create audio
        self.download_video()
        video_path, v_exists = self.get_file_path("video_path")

        if not video_path or not v_exists:
            raise RuntimeError(f"Video file not found for {self.video_id}")

        # Choose a sensible default audio file name if missing
        if not audio_path:
            base, _ = os.path.splitext(video_path)
            audio_path = base + ".wav"

        os.system(
            f"ffmpeg -y -i {video_path} -vn -acodec pcm_s16le -ar 16000 -ac 1 {audio_path}"
        )
        audio_format = audio_path.split(".")[-1]

        upsert_video(self.video_id, audio_path=audio_path, audio_format=audio_format)
        return audio_path, audio_format

    # === WHISPER ===
    def get_whisper(self):
        record = get_video_record(**self._video_context) or {}
        whisper_result = record.get("whisper")

        if record and whisper_result:
            return whisper_result

        audio_path, fmt = self.ensure_audio()
        result = whisper_transcribe(audio_path)

        upsert_video(self.video_id, whisper=result)
        return result

    # === CAPTIONS ===
    def get_captions(self):
        record = get_video_record(**self._video_context) or {}
        if record and record.get("captions"):
            return record["captions"]

        whisper = self.get_whisper()
        captions = [
            {"start": seg["start"], "end": seg["end"], "text": seg["text"]}
            for seg in whisper.get("segments", [])
        ]

        upsert_video(self.video_id, captions=captions)
        return captions

    # === METADATA ===
    def get_metadata(self):
        record = get_video_record(**self._video_context) or {}
        if record and record.get("metadata"):
            return record["metadata"]

        whisper = self.get_whisper()
        captions = self.get_captions()

        text_blob = " ".join([whisper.get("text", "")] + [c["text"] for c in captions])
        title = (
            self.info.get("title")
            or self.video_info.get("title")
            or text_blob[:50]
            or "Untitled"
        )
        summary = get_summarizer_summary(text=text_blob)

        keywords = self.info.get("keywords") or self.video_info.get("keywords") or []
        tags = self.info.get("tags") or self.video_info.get("tags") or []
        extracted_keywords = get_extracted_keywords(text=text_blob) or []
        keywords = make_list(keywords + tags + extracted_keywords)

        category = classify_category(make_list(keywords),title=title,description=summary)
        if len(keywords) >= 10:
            keywords = keywords[:10]

        metadata = {
            "title": title,
            "summary": summary,
            "category": category,
            "keywords": keywords,
        }

        upsert_video(self.video_id, metadata=metadata)
        return metadata

    # === THUMBNAILS ===
    def get_thumbnails(self):
        record = get_video_record(**self._video_context) or {}
        if record and record.get("thumbnails"):
            return record["thumbnails"]

        self.download_video()
        video_id = self.video_id
        video_path = self.video_info.get("video_path")
        thumbnails_dir = self.video_info.get("thumbnails_directory")
        
        thumbnails = get_thumbnails(video_id, video_path, thumbnails_dir)
        upsert_video(self.video_id, thumbnails=thumbnails)
        return thumbnails

    # === SEODATA ===
    def get_seodata(self):
        record = get_video_record(**self._video_context) or {}
        if record and record.get("seodata"):
            return record["seodata"]
        
        dl = VideoDownloader(url=self.video_url, download_video=True)
        whisper_result = self.get_whisper()
        captions = self.get_captions()

        thumbnails = self.get_thumbnails()
        thumbnails_dir = self.video_info.get("thumbnails_directory")
        thumbnails_paths = thumbnails.get("paths")
        
        metadata = self.get_metadata()
        title = metadata.get("title")
        summary = metadata.get("summary")
        keywords = metadata.get("keywords")
        description = metadata.get("description", summary)

        video_id = self.video_id
        video_path = self.video_info.get("video_path")
        if not (video_path and os.path.isfile(video_path)):
            file_map = get_file_map(video_path, types="video")
            video_paths = file_map.get("video")
            if video_paths:
                video_path = video_paths[0]

        audio_path = self.video_info.get("audio_path")
        if not (audio_path and os.path.isfile(audio_path)):
            file_map = get_file_map(video_path, types="audio")
            audio_paths = file_map.get("audio")
            if audio_paths:
                audio_path = audio_paths[0]

        seodata = get_seo_data(
            video_path=video_path,
            filename=video_id,
            title=title,
            summary=summary,
            description=description,
            keywords=keywords,
            thumbnails_dir=thumbnails_dir,
            thumbnail_paths=thumbnails_paths,
            whisper_result=whisper_result,
            audio_path=audio_path,
            domain="clownworld.biz",
        )

        # Store raw seodata (filesystem paths), frontend will get URL-converted
        upsert_video(self.video_id, seodata=seodata)
        return seodata

    # === AGGREGATED ===
    def get_aggregated_data(self):
        record = get_video_record(**self._video_context) or {}
        if record and record.get("aggregated"):
            return record["aggregated"]

        video_info = record.get("info") or {}
        directory = video_info.get("directory")
        aggregated = aggregate_from_base_dir(directory=directory)

        upsert_video(self.video_id, aggregated=aggregated)
        return aggregated

    # === METATAGS / META.JSON ===
    def get_meta_tags(self):
        """
        Build meta tags, persist them, and return a version where
        all filesystem/static paths are converted to public URLs.
        """
        record = get_video_record(**self._video_context) or {}
        if record and record.get("metatags"):
            return record["metatags"]
        data = self.get_all_data()
        return get_all_metadata(video_id = self.video_id,data = data)
    # === METATAGS / META.JSON ===
    def get_json_page(self):
        """
        Build meta tags, persist them, and return a version where
        all filesystem/static paths are converted to public URLs.
        """
        record = get_video_record(**self._video_context) or {}
        if record and record.get("pagedata"):
            return record["pagedata"]

        video_info = record.get("info") or {}
        directory = video_info.get("directory")
        video_url = video_info.get("video_url")
        self.get_meta_tags()
        pagedata = build_page_json(directory=directory,video_url = video_url,source_video_url = video_url)
        
        return pagedata
    # === METATAGS / META.JSON ===
    def get_extract_fields(self):
        """
        Build meta tags, persist them, and return a version where
        all filesystem/static paths are converted to public URLs.
        """
        extractfields = {}
        record = get_video_record(**self._video_context) or {}
        video_info = record.get("info") or {}
        directory = self.video_dir or video_info.get("directory")
        video_path = self.video_path or f"{directory}/video.mp4"
        video_id = str(self.video_id)
        basename = os.path.basename(video_path)
        filename,ext = os.path.splitext(basename)
        original_url = video_info.get("original_url") or self.video_url or video_info.get("video_url") 
        clownworld_video_url = f"https://clownworld.biz/videos/{video_id}/video.mp4"
        share_url = f"https://clownworld.biz/videos/?video_id={video_id}"
        video_url = original_url
        if is_file(video_path):
            video_url = clownworld_video_url
        extractfields["videoId"] = video_id
        extractfields["video_id"] = video_id
        extractfields["original_url"] = original_url
        extractfields["video_url"] = video_url
        extractfields["optimized_video_url"] = video_url
        extractfields["share_url"] =share_url
        info = self.get_info()
        for key in ["pagedata","metatags","seodata","thumbnails","metadata","rawdata"]:
            values = info.get(key)
            if values and isinstance(values,dict):
                nufields = [get_values(STRINGS_VARS,values) or {},extract_video_fields(values) or {}]
                for nufield in nufields:
                    for fkey,fval in nufield.items():
                            extractfields[fkey] = extractfields.get(fkey) or fval
        info.update(extractfields)
        meadata =  get_all_metadata(video_id=video_id,data=info)
        pagedata = build_page_json(directory=directory,video_url = video_url)
        extractfields['pagedata']=pagedata
        return extractfields
    # === INFO / ALL ===
    def get_info(self):
        self.get_rawdata()
        return get_video_record(**self._video_context) or {}
    # === INFO / ALL ===
    def get_video_url(self):
        rawdata = self.get_rawdata()
        record = get_video_record(**self._video_context) or {}
        return self.video_url or record.get('video_url') or record.get("info",{}).get('original_url')
        # === INFO / ALL ===
    def get_video_id(self):
        rawdata = self.get_rawdata()
        
        return self.video_id or record.get('video_id') or generate_video_id(self.video_url) or generate_video_id(self.video_path)
    def get_video_path(self):
        self.get_rawdata()
        return self.video_path or get_video_record(**self._video_context) or {}
    def get_video_dir(self):
        video_path = self.get_video_path()
        if video_path:
            return os.path.dirname(video_path)
    def get_video_record(self):
        record = get_video_record(**self._video_context) or {}
        if record:
            return record
    def get_all_data(self):
        return {
            "info": self.get_info(),
            "rawdata": self.get_rawdata(),
            "whisper": self.get_whisper(),
            "captions": self.get_captions(),
            "metadata": self.get_metadata(),
            "thumbnails": self.get_thumbnails(),
            "seodata": self.get_seodata(),
            "aggregated": self.get_aggregated_data(),
        }

    def get_all(self):
        return {
            "info": self.get_info(),
            "rawdata": self.get_rawdata(),
            "whisper": self.get_whisper(),
            "captions": self.get_captions(),
            "metadata": self.get_metadata(),
            "thumbnails": self.get_thumbnails(),
            "seodata": self.get_seodata(),
            "aggregated": self.get_aggregated_data(),
            "metatags": self.get_meta_tags(),
            "pagedata": self.get_json_page(),
        }


def get_local_db_data(*args,**kwargs):
    base_url = kwargs.get('base_url',"https://clownworld.biz")
    key = get_pipeline_key(kwargs.get('key'))
    p = VideoPipeline(*args,**kwargs)
    if p.video_url == None and p.video_path == None:
        return
    pipeline_js = {
        "info": p.get_info,
        "id": p.get_video_id,
        "url": p.get_video_url,
        "path": p.get_video_path,
        "record": p.get_video_record,
        "dir": p.get_video_dir,
        "raw": p.get_rawdata,
        "extract":p.get_extract_fields,
        "download": p.download_video,
        "audio": p.ensure_audio,
        "whisper": p.get_whisper,
        "captions": p.get_captions,
        "metadata": p.get_metadata,
        "thumbnails": p.get_thumbnails,
        "seodata": p.get_seodata,
        "metatags": p.get_meta_tags,
        "pagedata":p.get_json_page,
        "all": p.get_all,
    }
    
    
    def _call_and_convert(func):
        result = func
        if not isinstance(func,str):
            result = func()
        data = convert_paths_to_urls(result, base_url=base_url)
        return data
    if key:
        key = get_pipeline_key(key)
        func = pipeline_js.get(key)
        if func:
            return _call_and_convert(func)
    return _call_and_convert(p.get_all)
def get_pipeline_data(*args, **kwargs):
    engine = getHugpyDbEngine(*args, **kwargs)
    
    if not is_db_available(engine):
        url = "https://clownworld.biz/api/video/get_pipeline_data"
        return postRequest(url=url, data=kwargs)
    
    return get_local_db_data(*args, **kwargs)
