from .registry_functions import *
from .get_video_url_path import get_video_url_path_from_args
import inspect
import os

def _caller_summary(skip: int = 2, depth: int = 5) -> list[dict]:
    """
    Returns a compact call trace showing who called into this function.
    skip=2 skips this helper + the immediate wrapper.
    """
    frames = inspect.stack()[skip: skip + depth]
    out = []
    for f in frames:
        out.append({
            "file": os.path.basename(f.filename),
            "line": f.lineno,
            "func": f.function,
        })
    return out

class infoRegistry(metaclass=SingletonMeta):
    def __init__(self, video_root=None, documents_root=None, flat_layout: bool = False, **kwargs):
        if not hasattr(self, "initialized"):
            self.initialized = True
            self.db_mgr = getHugpyDbManager(**kwargs)
            self.engine = getHugpyDbEngine()
            
            self.videos_root = VIDEOS_ROOT_DEFAULT

    # ─────────────────────────────────────────────
    # Helper: make sure we always have a video_id
    # ─────────────────────────────────────────────
    def _normalize_video_id(self, videoId: Optional[str], data: Any) -> Optional[str]:
        """
        Ensure we end up with a non-empty video_id.

        Priority:
            1. explicit video_id argument
            2. data["video_id"]
            3. data["id"] (yt-dlp field)
        """
        if videoId:
            return str(videoId)

        if isinstance(data, dict):
            candidate = data.get("video_id") or data.get("id")
            if candidate:
                return str(candidate)

        return None

    def _upsert(self, videoId,**data):
        # 🔹 Derive a real id from the payload if needed

        videoId = self._normalize_video_id(videoId, data)

        # 🔹 Final guard: never write a NULL PK to the DB
        if not videoId:
            logger.warning(
                "infoRegistry._upsert called without a usable video_id; "
                "skipping upsert. data.id=%r",
                (data.get("id") if isinstance(data, dict) else None),
            )
            return

        # Also ensure the info blob itself carries the normalized id

        self.db_mgr.upsert_video(videoId,**data)


    def get_video_info(self, **kwargs):
        hide_audio = kwargs.get('hide_audio', True)
        force_refresh = kwargs.get('force_refresh', False)

        url, video_id, video_path, info, video_dir = get_video_url_path_from_args(**kwargs)

        # 🚨 Detect bad call immediately
        if not (url or video_id or video_path):
            logger.error(
                "❌ get_video_info called with NO identity. kwargs=%r caller=%r",
                kwargs,
                _caller_summary(),
            )
            return None
        logger.info(f"kwargs for get_video_info == {url,video_id,video_path,video_dir}")
        # ── 1) Try to derive video_id from url/path before DB / yt-dlp
        if not video_id:
            if url:
                video_id = get_video_id_from_url(url)
            elif video_path:
                video_id = generate_video_id(video_path)
        logger.info(f"kwargs2 for get_video_info == {url,video_id,video_path,video_dir}")

        # ── 2) If we *do* know video_id, see if it's already in DB
        if video_id:
            row_mapping = self.db_mgr.get_video_record(video_id=video_id,hide_audio=hide_audio)
            if row_mapping and not force_refresh:
                return row_mapping
        # ── 3) Hit yt-dlp
        info = get_yt_dlp_info(url) if url else {}
        logger.info(f"kwargs3 for get_video_info == {url,video_id,video_path,video_dir}")
        
        # If we *still* have nothing, bail out gracefully
        if not video_id:
            logger.warning(
                "get_video_info: could not determine video_id for url=%r, video_path=%r; "
                "skipping DB write.",
                url,
                video_path,
            )
            return None

        # Make sure the blob advertises the final id
        if isinstance(info, dict):
            info["video_id"] = video_id

        # Standardize paths before storage
        info = ensure_standard_paths(
            info,
            video_id=video_id,
            root_dir=self.videos_root,
            video_url=url,
            video_path=video_path,
        )
        
        if info and video_id:
            info["video_id"]= video_id
            self._upsert(video_id ,info=info)
            return info

        return None

    def edit_info(self, data, **kwargs):
        url,video_id,video_path,info,video_dir = get_video_url_path_from_args(**kwargs)

        # Keep the same normalization logic here too
        if not video_id:
            if url:
                video_id = get_video_id_from_url(url)
            elif video_path:
                video_id = generate_video_id(video_path)

        video_id = self._normalize_video_id(video_id, data)
        if not video_id:
            logger.warning(
                "edit_info called without a usable video_id; skipping edit. url=%r video_path=%r",
                url,
                video_path,
            )
            return None

        self._upsert(video_id, **data)
        return self.get_video_info(video_id=video_id, force_refresh=True)
def get_info_registry(video_root=None, documents_root=None, flat_layout: bool = False, **kwargs):
    return infoRegistry(video_root=video_root, documents_root=documents_root, flat_layout=flat_layout)
def upsert_video(video_id: str,video_root=None, documents_root=None, flat_layout: bool = False,**fields):
    info_registry = get_info_registry(video_root=video_root, documents_root=documents_root, flat_layout=flat_layout)

    return info_registry._upsert(video_id, **fields)
def get_video_record(force_refresh=False,hide_audio=True,video_root=None, documents_root=None, flat_layout: bool = False,**kwargs):
    info_registry = get_info_registry(video_root=video_root, documents_root=documents_root, flat_layout=flat_layout)
    url,video_id,video_path,info,video_dir = get_video_url_path_from_args(**kwargs)
    return info_registry.get_video_info(url=url, video_id=video_id, video_path=video_path, force_refresh=force_refresh,hide_audio=hide_audio)

