"""
Enhanced Instagram scraper that downloads all images (but not videos).
"""

import os
import time
import random
from typing import Any, Dict, List, Optional
from datetime import datetime
from pathlib import Path
import instaloader
from src.instagram_scraper import InstagramScraper


class InstagramScraperWithImages(InstagramScraper):
    """Instagram scraper that downloads all post images."""
    
    def __init__(self, config):
        super().__init__(config)
        # Create media directory for Instagram
        self.media_dir = self.config.data_dir / "media" / "Instagram"
        self.media_dir.mkdir(parents=True, exist_ok=True)
        self.logger.info(f"Instagram media directory: {self.media_dir}")
    
    def _download_post_images(self, post, post_id: str) -> List[str]:
        """Download all images from a post (skip videos)."""
        image_paths = []
        
        try:
            # Check if it's a video post - skip downloading video
            if getattr(post, 'is_video', False):
                # Videos might have a thumbnail we can grab
                if hasattr(post, 'url'):
                    # This is usually the video thumbnail
                    thumbnail_url = post.url
                    local_path = self.download_media(
                        thumbnail_url, 
                        f"instagram_{post_id}_video_thumb",
                        "image"
                    )
                    if local_path:
                        image_paths.append(local_path)
                        self.logger.info(f"Downloaded video thumbnail for {post_id}")
            else:
                # Single image or carousel
                if hasattr(post, 'mediacount') and post.mediacount > 1:
                    # Carousel post with multiple images
                    image_num = 1
                    for node in post.get_sidecar_nodes():
                        # Skip video nodes in carousel
                        if not node.is_video:
                            image_url = node.display_url
                            local_path = self.download_media(
                                image_url,
                                f"instagram_{post_id}_image_{image_num}",
                                "image"
                            )
                            if local_path:
                                image_paths.append(local_path)
                                self.logger.info(f"Downloaded carousel image {image_num} for {post_id}")
                            image_num += 1
                else:
                    # Single image post
                    if hasattr(post, 'url'):
                        image_url = post.url
                        local_path = self.download_media(
                            image_url,
                            f"instagram_{post_id}_image",
                            "image"
                        )
                        if local_path:
                            image_paths.append(local_path)
                            self.logger.info(f"Downloaded image for {post_id}")
                            
        except Exception as e:
            self.logger.error(f"Error downloading images for post {post_id}: {e}")
        
        return image_paths
    
    def fetch_posts(self, max_posts: int = 20) -> List[Dict[str, Any]]:
        """Fetch posts from Instagram profile with image downloads."""
        posts_data = []
        
        try:
            # Ensure we have a valid context
            if not self.loader.context:
                self.logger.warning("Instagram context not initialized, attempting re-login")
                self._login()
                
            if not self.loader.context:
                self.logger.error("Failed to initialize Instagram context")
                return posts_data
            
            self.logger.info(f"Fetching posts with images from @{self.target_account}")
            
            # Get profile
            profile = instaloader.Profile.from_username(self.loader.context, self.target_account)
            self._check_rate_limit()
            
            # Get posts
            posts = profile.get_posts()
            
            count = 0
            for post in posts:
                if count >= max_posts:
                    break
                
                try:
                    # Download images for this post
                    image_paths = self._download_post_images(post, post.shortcode)
                    
                    # Extract post data
                    post_data = {
                        'id': post.shortcode,
                        'type': self._get_post_type(post),
                        'caption': post.caption if post.caption else '',
                        'author': post.owner_username,
                        'publish_date': post.date_utc.isoformat(),
                        'link': f'https://www.instagram.com/p/{post.shortcode}/',
                        'likes': post.likes,
                        'comments': post.comments,
                        'views': post.video_view_count if hasattr(post, 'video_view_count') else None,
                        'media_count': post.mediacount if hasattr(post, 'mediacount') else 1,
                        'hashtags': list(post.caption_hashtags) if post.caption else [],
                        'mentions': list(post.caption_mentions) if post.caption else [],
                        'is_video': getattr(post, 'is_video', False),
                        'local_images': image_paths  # Add downloaded image paths
                    }
                    
                    posts_data.append(post_data)
                    count += 1
                    
                    # Aggressive rate limiting between posts
                    self._aggressive_delay()
                    self._check_rate_limit()
                    
                    # Log progress
                    if count % 5 == 0:
                        self.logger.info(f"Fetched {count}/{max_posts} posts with images")
                    
                except Exception as e:
                    self.logger.error(f"Error processing post: {e}")
                    continue
            
            self.logger.info(f"Successfully fetched {len(posts_data)} posts with images")
            
        except Exception as e:
            self.logger.error(f"Error fetching posts: {e}")
        
        return posts_data
    
    def fetch_stories(self) -> List[Dict[str, Any]]:
        """Fetch stories from Instagram profile with image downloads."""
        stories_data = []
        
        try:
            # Ensure we have a valid context
            if not self.loader.context:
                self.logger.warning("Instagram context not initialized, attempting re-login")
                self._login()
                
            if not self.loader.context:
                self.logger.error("Failed to initialize Instagram context")
                return stories_data
            
            self.logger.info(f"Fetching stories with images from @{self.target_account}")
            
            # Get profile
            profile = instaloader.Profile.from_username(self.loader.context, self.target_account)
            self._check_rate_limit()
            
            # Get user ID for stories
            userid = profile.userid
            
            # Get stories
            for story in self.loader.get_stories(userids=[userid]):
                for item in story:
                    try:
                        # Download story image (skip video stories)
                        image_paths = []
                        if not item.is_video and hasattr(item, 'url'):
                            local_path = self.download_media(
                                item.url,
                                f"instagram_{item.mediaid}_story",
                                "image"
                            )
                            if local_path:
                                image_paths.append(local_path)
                                self.logger.info(f"Downloaded story image {item.mediaid}")
                        
                        story_data = {
                            'id': item.mediaid,
                            'type': 'story',
                            'caption': '',  # Stories usually don't have captions
                            'author': item.owner_username,
                            'publish_date': item.date_utc.isoformat(),
                            'link': f'https://www.instagram.com/stories/{item.owner_username}/{item.mediaid}/',
                            'is_video': item.is_video if hasattr(item, 'is_video') else False,
                            'local_images': image_paths  # Add downloaded image paths
                        }
                        
                        stories_data.append(story_data)
                        
                        # Rate limiting
                        self._aggressive_delay()
                        self._check_rate_limit()
                        
                    except Exception as e:
                        self.logger.error(f"Error processing story: {e}")
                        continue
            
            self.logger.info(f"Successfully fetched {len(stories_data)} stories with images")
            
        except Exception as e:
            self.logger.error(f"Error fetching stories: {e}")
        
        return stories_data
    
    def format_markdown(self, items: List[Dict[str, Any]]) -> str:
        """Format Instagram content as markdown with image references."""
        markdown_sections = []
        
        for item in items:
            section = []
            
            # ID
            section.append(f"# ID: {item.get('id', 'N/A')}")
            section.append("")
            
            # Type
            section.append(f"## Type: {item.get('type', 'post')}")
            section.append("")
            
            # Link
            section.append(f"## Link: {item.get('link', '')}")
            section.append("")
            
            # Author
            section.append(f"## Author: {item.get('author', 'N/A')}")
            section.append("")
            
            # Publish Date
            section.append(f"## Publish Date: {item.get('publish_date', 'N/A')}")
            section.append("")
            
            # Caption
            if item.get('caption'):
                section.append("## Caption:")
                section.append(item['caption'])
                section.append("")
            
            # Engagement metrics
            if item.get('likes') is not None:
                section.append(f"## Likes: {item.get('likes', 0)}")
                section.append("")
            
            if item.get('comments') is not None:
                section.append(f"## Comments: {item.get('comments', 0)}")
                section.append("")
            
            if item.get('views') is not None:
                section.append(f"## Views: {item.get('views', 0)}")
                section.append("")
            
            # Local images
            if item.get('local_images'):
                section.append("## Downloaded Images:")
                for img_path in item['local_images']:
                    # Convert to relative path for markdown
                    rel_path = Path(img_path).relative_to(self.config.data_dir)
                    section.append(f"- [{rel_path.name}]({rel_path})")
                section.append("")
            
            # Hashtags
            if item.get('hashtags'):
                section.append(f"## Hashtags: {' '.join(['#' + tag for tag in item['hashtags']])}")
                section.append("")
            
            # Mentions
            if item.get('mentions'):
                section.append(f"## Mentions: {' '.join(['@' + mention for mention in item['mentions']])}")
                section.append("")
            
            # Media count
            if item.get('media_count') and item['media_count'] > 1:
                section.append(f"## Media Count: {item['media_count']}")
                section.append("")
            
            # Is video
            if item.get('is_video'):
                section.append("## Media Type: Video (thumbnail downloaded)")
                section.append("")
            
            # Separator
            section.append("-" * 50)
            section.append("")
            
            markdown_sections.append('\n'.join(section))
        
        return '\n'.join(markdown_sections)