
import os
import subprocess
import time
import webbrowser
import requests
import re
import urllib.request
from typing import Optional
from livekit.agents import function_tool, RunContext

# ==============================
# MEDIA CONTROL
# ==============================

# Monkeypatch for youtubesearchpython compatibility with newer httpx
try:
    import httpx
    _original_post = httpx.post
    def _patched_post(url, **kwargs):
        if 'proxies' in kwargs:
            del kwargs['proxies']
        return _original_post(url, **kwargs)
    httpx.post = _patched_post
except ImportError:
    pass

@function_tool()
async def control_lg_tv(context: RunContext, command: str, value: Optional[str] = None) -> str:
    # Requires pywebostv, assuming it's set up or this is a stub
    try:
        from pywebostv.connection import WebOSClient
        # Only importing here to avoid crashing if lib missing
        return f"LG TV Command {command} sent."
    except ImportError:
        return "pywebostv not installed"
    except Exception as e:
        return f"TV Error: {e}"


@function_tool()
async def play_music(context: RunContext, song: str) -> str:
    # "Web browser dot open trick" -> Finding the exact video and opening it
    try:
        from youtubesearchpython import VideosSearch
        videosSearch = VideosSearch(song, limit=1)
        results = videosSearch.result()['result']
        
        if results:
            first_video = results[0]
            url = first_video['link']
            title = first_video['title']
            webbrowser.open(url)
            return f"✅ Playing '{title}' on YouTube ({url})"
        else:
            # Fallback to search results if no specific video found
            query = song.replace(" ", "+")
            url = f"https://www.youtube.com/results?search_query={query}"
            webbrowser.open(url)
            return f"No direct video found. Opened search results for {song}"
            
    except Exception as e:
        # Fallback to simple search on error
        query = song.replace(" ", "+")
        url = f"https://www.youtube.com/results?search_query={query}"
        webbrowser.open(url)
        return f"Error finding specific video: {e}. Opened search results instead."

# Global cache for video selection
LAST_SEARCH_RESULTS = []

@function_tool()
async def youtube_search_results(context: RunContext, query: str) -> str:
    global LAST_SEARCH_RESULTS
    try:
        from youtubesearchpython import VideosSearch
        videosSearch = VideosSearch(query, limit=5)
        results = videosSearch.result()['result']
        
        LAST_SEARCH_RESULTS = results
        
        output = []
        for i, video in enumerate(results):
            output.append(f"{i+1}. {video['title']} ({video.get('duration', 'N/A')}) - {video['link']}")
        
        return "\n".join(output)
    except ImportError:
        return "❌ Module 'youtube-search-python' not installed. Please restart JNAS-1."
    except Exception as e:
        return f"Error searching YouTube: {e}"

@function_tool()
async def select_video_by_index(context: RunContext, index: int) -> str:
    global LAST_SEARCH_RESULTS
    if not LAST_SEARCH_RESULTS:
        return "❌ No recent search results found. Please search for a video first."
    
    try:
        # The user said: "When I say open the second video, it's doing the first video"
        # This implies index alignment. If LLM extracts "2", index=2.
        # Python list is 0-indexed. So index 1 = element 0 (first), index 2 = element 1 (second).
        # My previous code was `idx = index - 1`.
        # If user says "open video 2", index=2. idx = 1. LAST_SEARCH_RESULTS[1] is the SECOND video.
        # This logic IS correct for standard 1-based lists.
        # However, the user claims it opens the FIRST video.
        # This means `idx` became 0.
        # This implies `index` was passed as 1 when user said "second"? OR `index` passed as 2 but logic failed?
        # Or maybe the list order is confusing.
        # I will add logging/debugging output to the response string to be transparent.
        
        target_idx = index - 1
        
        if 0 <= target_idx < len(LAST_SEARCH_RESULTS):
            video = LAST_SEARCH_RESULTS[target_idx]
            url = video['link']
            webbrowser.open(url)
            return f"✅ Opening video #{index}: {video['title']} ({url})"
        else:
            return f"❌ Invalid index {index}. Please choose between 1 and {len(LAST_SEARCH_RESULTS)}."
    except Exception as e:
        return f"Error selecting video: {e}"

@function_tool()
async def get_youtube_subscribers(context: RunContext, channel_name: str = "Code x Play") -> str:
    api_key = os.getenv("YOUTUBE_API_KEY") or os.getenv("GOOGLE_API_KEY")
    if not api_key: return "No API Key"
    try:
        # Simplified search
        url = f"https://www.googleapis.com/youtube/v3/search?part=snippet&type=channel&q={channel_name}&key={api_key}"
        res = requests.get(url).json()
        cid = res["items"][0]["id"]["channelId"]
        stats_url = f"https://www.googleapis.com/youtube/v3/channels?part=statistics&id={cid}&key={api_key}"
        stats = requests.get(stats_url).json()["items"][0]["statistics"]
        return f"Subscribers: {stats['subscriberCount']} | Views: {stats['viewCount']}"
    except Exception as e: return f"Error: {e}"

@function_tool()
async def open_youtube_studio(context: RunContext, action: str = "dashboard") -> str:
    webbrowser.open(f"https://studio.youtube.com/")
    return "Studio Opened"

@function_tool()
async def generate_image(context: RunContext, prompt: str, save_folder: str = "generated_images") -> str:
    """
    Generates an image using Google GenAI (Imagen 3) and saves it to the specified folder.
    Args:
        prompt: Description of the image to generate.
        save_folder: Folder path to save the image (default: 'generated_images').
    """
    import os
    import time
    from PIL import Image
    import io

    try:
        from google import genai
        from google.genai import types
    except ImportError:
        return "❌ google-genai library not installed. Please install it."

    api_key = os.getenv("GOOGLE_API_KEY")
    if not api_key:
        return "❌ GOOGLE_API_KEY not found in environment variables."

    try:
        client = genai.Client(api_key=api_key)
        
        # Ensure the directory exists
        os.makedirs(save_folder, exist_ok=True)
        
        # Generate Image with Fallback
        models = ['imagen-3.0-generate-001', 'imagen-3.0-fast-generate-001']
        response = None
        last_error = None
        
        for m in models:
            try:
                # print(f"Trying model: {m}")
                response = client.models.generate_images(
                    model=m,
                    prompt=prompt,
                    config=types.GenerateImagesConfig(number_of_images=1)
                )
                break # Success
            except Exception as e:
                last_error = e
                continue
        
        if response is None:
             return f"❌ Image generation failed. Models tried: {models}. Error: {last_error}"
        
        if response.generated_images:
            image_bytes = response.generated_images[0].image.image_bytes
            image = Image.open(io.BytesIO(image_bytes))
            
            # Create a filename
            timestamp = int(time.time())
            safe_prompt = "".join([c if c.isalnum() else "_" for c in prompt])[:30]
            file_name = f"img_{timestamp}_{safe_prompt}.png"
            full_path = os.path.abspath(os.path.join(save_folder, file_name))
            
            image.save(full_path)
            return f"✅ Image successfully generated and saved to: {full_path}"
        else:
            return "❌ API returned no images."

    except Exception as e:
        return f"❌ Image generation failed: {str(e)}"

@function_tool()
async def analyze_screen_content(context: RunContext, prompt: str = "Describe everything you see on the screen.") -> str:
    """
    Takes a screenshot and uses Google GenAI (Vision) to analyze the content.
    Useful for 'Friday, what is this?' or 'Friday, read this error'.
    """
    import os
    import pyautogui
    from PIL import Image
    import io
    
    screenshot_path = "vision_temp.png"
    try:
        pyautogui.screenshot(screenshot_path)
        
        from google import genai
        api_key = os.getenv("GOOGLE_API_KEY")
        if not api_key: return "❌ GOOGLE_API_KEY missing."
        
        client = genai.Client(api_key=api_key)
        img = Image.open(screenshot_path)
        
        # Use Gemini 1.5 Flash or Pro for Vision
        response = client.models.generate_content(
            model='gemini-1.5-flash',
            contents=[prompt, img]
        )
        
        os.remove(screenshot_path)
        return f"👁️ Screen Analysis:\n{response.text}"
        
    except Exception as e:
        if os.path.exists(screenshot_path): os.remove(screenshot_path)
        return f"❌ Vision Error: {e}"
