import os
import random
import time
import getpass
from datetime import datetime, timedelta
from colorama import Fore, Style, init
from instagrapi import Client
from instagrapi.exceptions import (
    LoginRequired, ChallengeRequired,
    ClientError, ClientConnectionError
)

# Initialize console colors
init(autoreset=True)

class InstagramBot:
    def __init__(self):
        self.client = Client()
        self.config = {
            'session_file': 'ig_session.json',
            'delays': {
                'like': (6, 12),
                'comment': (12, 18),
                'action': (4, 8),
                'suspicion': (300, 900)
            },
            'comments': [
                "Absolutely love this character's design! 💖✨",
                "This artwork is simply breathtaking! 🌟😍",
                "Such vibrant colors! It really brings the character to life! 🎨💫",
                "I can’t get enough of this anime! So much talent here! 🌈🙌",
                "This scene is iconic! Love how you captured it! 💖🎉"
            ],
            'max_post_age': timedelta(hours=1)  # New time filter
        }
        self.stats = {
            'likes': 0,
            'comments': 0,
            'failures': 0,
            'start_time': None
        }

    def _print(self, type_, message):
        """Color-coded console output"""
        colors = {
            'info': Fore.CYAN,
            'success': Fore.GREEN,
            'warning': Fore.YELLOW,
            'error': Fore.RED,
            'header': Fore.MAGENTA,
            'input': Fore.BLUE
        }
        print(f"{colors[type_]}{Style.BRIGHT}{message}{Style.RESET_ALL}")

    def _get_input(self, prompt, is_password=False):
        """Secure input handling with color"""
        self._print('input', f"\n{prompt}")
        return getpass.getpass("") if is_password else input()

    def setup(self):
        """Interactive configuration setup"""
        self._print('header', "\n" + "="*40)
        self._print('header', "Instagram Bot Configuration")
        self._print('header', "="*40)

        # Credentials
        self.config['username'] = self._get_input("Enter your Instagram username:")
        self.config['password'] = self._get_input("Enter your Instagram password:", is_password=True)

        # Hashtag configuration
        use_default_hashtags = self._get_input(
            "Use default hashtags? (y/n) [y]: "
        ).lower() or 'y'
        
        if use_default_hashtags == 'n':
            hashtags_input = self._get_input(
                "Enter target hashtags (comma-separated): "
            )
            self.config['hashtags'] = [h.strip() for h in hashtags_input.split(',') if h.strip()]
        else:
            self.config['hashtags'] = ['animeart', 'animefanart', 'animedesign']

        # Post limits
        while True:
            max_posts = self._get_input(
                "Max posts per hashtag [50]: "
            )
            try:
                self.config['max_posts'] = int(max_posts) if max_posts else 50
                break
            except ValueError:
                self._print('error', 'Please enter a valid integer!')

    def _handle_challenge(self):
        """Handle Instagram security challenges"""
        self._print('warning', "Security challenge detected!")
        try:
            challenge_info = self.client.challenge_resolve(self.client.last_json)
            
            if challenge_info['step_name'] == "select_verify_method":
                for method in challenge_info['methods']:
                    self._print('info', f"Available method: {method['label']}")
                
                chosen_method = self._get_input("Select verification method (sms/email): ")
                self.client.challenge_select(challenge_info['path'], chosen_method)
                
            self._print('info', f"Check your {chosen_method} for verification code")
            code = self._get_input("Enter 6-digit verification code: ")
            self.client.challenge_send(code)
            self.client.dump_settings(self.config['session_file'])
            return True
            
        except Exception as e:
            self._print('error', f"Challenge failed: {str(e)}")
            return False

    def _validate_session(self):
        """Validate existing session"""
        try:
            self.client.get_timeline_feed()
            return True
        except Exception as e:
            self._print('warning', f"Session validation failed: {str(e)}")
            return False

    def login(self):
        """Enhanced login with session validation"""
        session_file = self.config['session_file']
        
        try:
            if os.path.exists(session_file):
                self.client.load_settings(session_file)
                if self._validate_session():
                    self._print('success', "Session restored successfully!")
                    return True
                self._print('warning', "Session expired, re-logging in...")
                os.remove(session_file)

            # Fresh login
            self.client.login(self.config['username'], self.config['password'])
            self.client.dump_settings(session_file)
            self._print('success', "Login successful!")
            return True
            
        except ChallengeRequired:
            return self._handle_challenge()
        except Exception as e:
            self._print('error', f"Login failed: {str(e)}")
            return False

    def _is_recent_post(self, post_time):
        """Check if post is within 1 hour"""
        now = datetime.now(post_time.tzinfo)
        return (now - post_time) <= self.config['max_post_age']

    def search_recent_posts(self):
        """Fetch and filter posts from last hour"""
        posts = []
        try:
            for hashtag in self.config['hashtags']:
                self._print('header', f"\nScanning #{hashtag}...")
                try:
                    # Fetch recent posts with extended limit
                    medias = self.client.hashtag_medias_recent(
                        hashtag, 
                        amount=min(self.config['max_posts'], 100)
                    
                    # Filter by time
                    valid_posts = [
                        post for post in medias
                        if self._is_recent_post(post.taken_at)
                    ]
                    
                    posts.extend(valid_posts)
                    self._print('info', 
                        f"Found {len(valid_posts)}/{len(medias)} recent posts "
                        f"(last hour)"
                    )
                    time.sleep(random.uniform(5, 10))
                except Exception as e:
                    self._print('error', f"Error scanning #{hashtag}: {str(e)}")
                    continue

        except Exception as e:
            self._print('error', f"Search failed: {str(e)}")
            
        finally:
            self._print('success', f"\nTotal valid posts: {len(posts)}")
            return posts

    def _validate_post(self, post):
        """Comprehensive post validation"""
        required_attrs = ['id', 'taken_at', 'user', 'media_type']
        if not all(hasattr(post, attr) for attr in required_attrs):
            return False
            
        try:
            if not self._is_recent_post(post.taken_at):
                return False
                
            if post.media_type not in [1, 2, 8]:
                return False
                
            return True
            
        except Exception:
            return False

    def interact_with_posts(self, posts):
        """Hour-filtered interaction system"""
        self.stats['start_time'] = datetime.now()
        
        for i, post in enumerate(posts, 1):
            try:
                if not self._validate_post(post):
                    self._print('warning', f"Skipping invalid post {i}")
                    continue

                post_time = post.taken_at.astimezone()
                time_str = post_time.strftime("%H:%M:%S")
                age = datetime.now(post_time.tzinfo) - post_time
                minutes = age.seconds // 60
                seconds = age.seconds % 60

                self._print('info', f"\nPost {i}/{len(posts)}")
                self._print('info', f"Posted at: {time_str} ({minutes}m {seconds}s ago)")
                self._print('info', f"Type: {post.media_type} | Views: {getattr(post, 'view_count', 'N/A')}")

                # Like interaction
                if random.random() < 0.7 and not post.has_liked:
                    self.client.media_like(post.id)
                    self.stats['likes'] += 1
                    self._print('success', "Liked post")
                    time.sleep(random.uniform(*self.config['delays']['like']))

                # Comment interaction
                if random.random() < 0.3:
                    comment = random.choice(self.config['comments'])
                    self.client.media_comment(post.id, comment)
                    self.stats['comments'] += 1
                    self._print('success', f"Commented: {comment}")
                    time.sleep(random.uniform(*self.config['delays']['comment']))

                # Random action delay
                time.sleep(random.uniform(*self.config['delays']['action']))

            except (ClientError, ClientConnectionError) as e:
                self.stats['failures'] += 1
                self._print('error', f"Interaction error: {str(e)}")
                self._handle_suspicion()
            except Exception as e:
                self.stats['failures'] += 1
                self._print('error', f"Unexpected error: {str(e)}")

    def _handle_suspicion(self):
        """Improved suspicion handling"""
        delay = random.randint(*self.config['delays']['suspicion'])
        self._print('warning', f"Safety cooldown: {delay//60}m")
        time.sleep(delay)

    def show_report(self):
        """Detailed performance report"""
        duration = datetime.now() - self.stats['start_time']
        self._print('header', '\n' + '='*40)
        self._print('success', "Hourly Activity Report:")
        self._print('info', f"Session Duration: {duration}")
        self._print('info', f"Likes Sent: {self.stats['likes']}")
        self._print('info', f"Comments Posted: {self.stats['comments']}")
        self._print('info', f"Failed Actions: {self.stats['failures']}")
        self._print('header', '='*40)

if __name__ == "__main__":
    bot = InstagramBot()
    bot.setup()
    
    if bot.login():
        posts = bot.search_recent_posts()
        if posts:
            bot.interact_with_posts(posts)
            bot.show_report()  صحح جميع الاخطاء واعطيني السكريبت بدون شرح