"""
Instagram scraper using yt-dlp for reliable media extraction.

Note: Most Instagram features require login cookies.
Configure INSTAGRAM_COOKIE_FILE or COOKIES_FROM_BROWSER in .env.
"""

import re
from datetime import datetime

import yt_dlp

from backend.core.config import settings


class InstagramScraper:
    """Instagram scraper using yt-dlp. Most features require login cookies."""

    def __init__(self):
        self.cookies_file = settings.INSTAGRAM_COOKIE_FILE or None
        self.cookies_browser = settings.COOKIES_FROM_BROWSER or None

    def _get_opts(self, max_results: int = 20) -> dict:
        opts = {
            "quiet": True,
            "no_warnings": True,
            "ignoreerrors": True,
            "no_color": True,
            "playlistend": max_results,
            "socket_timeout": 30,
        }
        if self.cookies_file:
            opts["cookiefile"] = self.cookies_file
        elif self.cookies_browser:
            opts["cookiesfrombrowser"] = (self.cookies_browser,)
        return opts

    def search_hashtag(
        self, hashtag: str, max_results: int = 20
    ) -> list[dict]:
        """Search Instagram posts by hashtag."""
        tag = hashtag.strip().lstrip("#")
        if not tag:
            return []
        url = f"https://www.instagram.com/explore/tags/{tag}/"
        return self._extract_videos(url, max_results)

    def get_user_reels(
        self, username: str, max_results: int = 12
    ) -> list[dict]:
        """Get reels from a specific user."""
        username = username.strip().lstrip("@")
        if not username:
            return []

        # Try reels page first, then profile
        url = f"https://www.instagram.com/{username}/reels/"
        videos = self._extract_videos(url, max_results)
        if not videos:
            url = f"https://www.instagram.com/{username}/"
            videos = self._extract_videos(url, max_results)
        return videos

    def get_reels_from_url(self, reel_url: str) -> dict | None:
        """Get info for a specific reel URL."""
        opts = self._get_opts(1)
        opts["noplaylist"] = True
        try:
            with yt_dlp.YoutubeDL(opts) as ydl:
                info = ydl.extract_info(reel_url, download=False)
                if info:
                    return self._parse_entry(info)
        except Exception as e:
            print(f"[Instagram] Error getting reel info: {e}")
        return None

    def search_explore(self, max_results: int = 20) -> list[dict]:
        """Get posts from Instagram explore (requires cookies)."""
        url = "https://www.instagram.com/explore/"
        videos = self._extract_videos(url, max_results)
        if not videos:
            print(
                "[Instagram] Explore requires login cookies. "
                "Configure INSTAGRAM_COOKIE_FILE ou COOKIES_FROM_BROWSER no .env"
            )
        return videos

    def _extract_videos(self, url: str, max_results: int) -> list[dict]:
        """Extract videos from an Instagram URL using yt-dlp."""
        opts = self._get_opts(max_results)
        try:
            with yt_dlp.YoutubeDL(opts) as ydl:
                result = ydl.extract_info(url, download=False)
                if not result:
                    return []

                # Single video/post
                if "entries" not in result:
                    parsed = self._parse_entry(result)
                    return [parsed] if parsed else []

                # Playlist (user page, tag page, etc.)
                videos = []
                for entry in result.get("entries") or []:
                    if entry is None:
                        continue
                    parsed = self._parse_entry(entry)
                    if parsed:
                        videos.append(parsed)
                    if len(videos) >= max_results:
                        break

                return videos
        except Exception as e:
            print(f"[Instagram] Extraction error for {url}: {e}")
            return []

    def _parse_entry(self, entry: dict) -> dict | None:
        """Parse a yt-dlp entry into our standard format."""
        try:
            video_id = str(
                entry.get("id", "") or entry.get("display_id", "")
            )
            if not video_id:
                return None

            uploader = (
                entry.get("uploader", "")
                or entry.get("channel", "")
                or ""
            )
            uploader_id = (
                entry.get("uploader_id", "")
                or entry.get("channel_id", "")
                or ""
            )

            description = entry.get("description", "") or ""
            title = entry.get("title", "") or description[:200]
            hashtags = re.findall(r"#(\w+)", description)

            published_at = None
            ts = entry.get("timestamp")
            if ts:
                try:
                    published_at = datetime.fromtimestamp(int(ts))
                except (ValueError, TypeError, OSError):
                    pass
            elif entry.get("upload_date"):
                try:
                    published_at = datetime.strptime(
                        entry["upload_date"], "%Y%m%d"
                    )
                except ValueError:
                    pass

            webpage_url = entry.get("webpage_url", "")
            if not webpage_url:
                webpage_url = f"https://www.instagram.com/reel/{video_id}/"

            return {
                "platform": "instagram",
                "external_id": video_id,
                "url": webpage_url,
                "title": title[:200],
                "description": description[:500],
                "hashtags": hashtags[:20],
                "creator_username": uploader_id or uploader,
                "creator_display_name": uploader,
                "views": int(entry.get("view_count") or 0),
                "likes": int(entry.get("like_count") or 0),
                "comments": int(entry.get("comment_count") or 0),
                "shares": 0,
                "duration": int(entry.get("duration") or 0),
                "thumbnail_url": entry.get("thumbnail", "") or "",
                "published_at": published_at,
                "is_video": True,
            }
        except Exception as e:
            print(f"[Instagram] Parse error: {e}")
            return None

    def close(self):
        pass  # No persistent connection with yt-dlp
