from instabot import Bot
import os
import glob
import time
import random
from dotenv import load_dotenv
import ast

# Load the .env file
load_dotenv()
credentials = os.getenv("credentials")
bot = Bot() 
credentials = ast.literal_eval(credentials)

username = random.choice(list(credentials.keys()))
password = credentials[username]
print(username)
# Clear existing cookies to avoid login conflicts
cookie_del = glob.glob("config/*cookie.json")
if cookie_del:
	os.remove(cookie_del[0])

try:
	bot.login(username=username, password=password)
	time.sleep(random.uniform(1, 3))
	print("Login successful")
except Exception as e:
	if 'challenge_required' in str(e):
		print("Challenge required. Please verify your identity manually.")
	else:
		print(f"Login failed: {e}")
	exit()

# Cache to store likers
likers_cache = {}


def check_user_info(user):
	print(f"Fetching info for user: {user}")
	try:
		user_info = bot.get_user_info(user)
		if not user_info:
			return False
		return user_info['is_private']
	except Exception as e:
		print(f"Error fetching user info for {user}: {e}")
		return False


def get_likers(media_id):
	"""Fetch likers for a media ID with caching and retries."""
	if media_id in likers_cache:
		print(f"Using cached likers for media ID {media_id}.")
		return likers_cache[media_id]

	retries = 0
	while retries < 5:
		try:
			likers = bot.get_media_likers(media_id)
			likers_cache[media_id] = likers  # Cache results
			time.sleep(random.uniform(2, 4))  # Random sleep to mimic human behavior
			return likers
		except Exception as e:
			retries += 1
			print(f"Error fetching likers for media ID {media_id}: {e}")
			if '429' in str(e):
				print("Rate limit reached. Retrying after delay...")
				time.sleep(60 * (2 ** retries))  # Exponential backoff for rate limits
			else:
				time.sleep(random.uniform(2, 5))
	return []


def has_user_liked_post(data, username):
	"""Check if a user has liked specific posts."""
	print(f"Checking if user {username} has liked posts...")
	result = []

	try:
		user_id = bot.get_user_id_from_username(username)
		print(f"User ID for {username}: {user_id}")
	except Exception as e:
		print(f"Failed to fetch user ID for {username}: {e}")
		return [False] * len(data)

	for post_url in data:
		retries = 0
		while retries < 5:
			try:
				media_id = bot.get_media_id_from_link(post_url)
				if not media_id:
					print(f"Invalid media URL: {post_url}")
					result.append(False)
					break

				likers = get_likers(media_id)
				print(likers)
				if likers:
					print(f"Likers for media ID {media_id}: {len(likers)}")
					
					media_info = bot.get_media_info(media_id)
					total_likes = media_info[0]['like_count']
					print('total_likes',total_likes)
					if user_id in likers:
						print("in if")
						result.append(True)
					elif total_likes<=len(likers):
						print("in elif")
						result.append(True)
					elif total_likes>=100:
						print("in elif")
						result.append(True)
					else:
						print("in else")
						result.append(False)
					
				else:
					print(f"No likers found for media ID {media_id}.")
					result.append(True)
				
				time.sleep(random.uniform(1, 3))  # Random delay to mimic human behavior
				break

			except Exception as e:
				retries += 1
				print(f"Error processing post URL {post_url}: {e}")
				if '429' in str(e):
					print("Rate limit hit. Backing off...")
					time.sleep(60 * (2 ** retries))
				else:
					time.sleep(random.uniform(2, 5))

		if retries >= 5:
			print(f"Max retries exceeded for post URL {post_url}.")
			result.append(False)

	print(f"Results: {result}")
	return result


comments_cache = {}

def get_commenters(media_id):
	"""Get commenters for a media ID, using cache if available."""
	if media_id in comments_cache:
		print(f"Using cached comments for media ID {media_id}.")
		return comments_cache[media_id]
	try:
		commenters = bot.get_media_commenters(media_id)
		comments_cache[media_id] = commenters  # Store in cache
		time.sleep(random.uniform(2, 4))  # Random sleep after fetching commenters
		return commenters
	except Exception as e:
		print(f"Error fetching commenters for media ID {media_id}: {e}")
		return []

def has_user_commented_post(data, username):
	print("has_user_commented_post")
	result = []

	try:
		user_id = bot.get_user_id_from_username(username)
		print(f"User ID for {username}: {user_id}")
	except Exception as e:
		print(f"Failed to get user ID for username {username}: {e}")
		user_id = None

	if not user_id:
		return [False] * len(data)

	for post_url in data:
		retries = 0
		while retries < 5:
			try:
				media_id = bot.get_media_id_from_link(post_url)
				if media_id:
					media_info = bot.get_media_info(media_id)
					if len(media_info)<=0:
						result.append(True)
						break # Media ID found, append False
				elif check_user_info(user_id):
					result.append(True)
				# else:
				#     result.append(True)

				# Get commenters from cache or fetch them if not cached
				commenters = get_commenters(media_id)
				print(f"Commenters for media ID {media_id}: {commenters}")

				result.append(user_id in commenters)
				time.sleep(random.uniform(1, 3))  # Random sleep after processing each post
				break
			
			except Exception as e:
				print(f"Error processing post URL {post_url}: {e}")
				retries += 1
				if '429' in str(e):
					print("Rate limit reached. Pausing all operations.")
					time.sleep(60)  # Or use a backoff strategy
				else:
					time.sleep(random.uniform(2, 5))  # Random wait for other errors
				continue
		
		if retries >= 5:
			result.append(False)

	print(result)
	return result


def has_user_interacted_with_post(data, username):
	print("has_user_interacted_with_post")
	result = []

	try:
		user_id = bot.get_user_id_from_username(username)
		print(f"User ID for {username}: {user_id}")
	except Exception as e:
		print(f"Failed to get user ID for username {username}: {e}")
		user_id = None

	if not user_id:
		return [False] * len(data)

	for post_url in data:
		retries = 0
		while retries < 5:
			try:
				media_id = bot.get_media_id_from_link(post_url)
				if media_id:
					media_info = bot.get_media_info(media_id)
					if len(media_info)<=0:
						result.append(True)
						break # Media ID found, append False
				else:
					result.append(True)
					break

				# Get likers and commenters
				likers = get_likers(media_id)
				commenters = get_commenters(media_id)
				
				print(f"Likers for media ID {media_id}: {likers}")
				print(f"Commenters for media ID {media_id}: {commenters}")

				# Check if user has liked or commented
				interacted = (user_id in likers) or (user_id in commenters)
				result.append(interacted)
				time.sleep(random.uniform(1, 3))  # Random sleep after processing each post
				break
			
			except Exception as e:
				print(f"Error processing post URL {post_url}: {e}")
				retries += 1
				if '429' in str(e):
					print("Rate limit reached. Pausing all operations.")
					time.sleep(60)  # Or use a backoff strategy
				else:
					time.sleep(random.uniform(2, 5))  # Random wait for other errors
				continue
		
		if retries >= 5:
			result.append(False)


	return result




