import asyncio
import time
import os
from urllib.parse import urlparse
from WebStreamer.bot import StreamBot
from WebStreamer.utils.file_properties import gen_link
from WebStreamer.vars import Var
from pyrogram import filters, Client
from pyrogram.errors import FloodWait
from pyrogram.types import Message
from pyrogram.enums.parse_mode import ParseMode

def is_valid_url(url):
    """Validate URL format"""
    try:
        if not url or not isinstance(url, str):
            return False
        if not url.startswith(('http://', 'https://')):
            return False
        if any(c in url for c in [' ', '\n', '\t']):
            return False
        parsed = urlparse(url)
        return all([parsed.scheme, parsed.netloc])
    except:
        return False

def sanitize_url(url):
    """Clean and standardize URLs"""
    try:
        if not url:
            return None
            
        url = str(url).strip()
        
        # Fix multiple protocols
        while url.startswith(('https://https://', 'http://http://')):
            if url.startswith('https://https://'):
                url = url[8:]
            else:
                url = url[7:]
        
        # Ensure proper protocol
        if not url.startswith(('http://', 'https://')):
            url = 'https://' + url
            
        # Remove any whitespace or control characters
        url = ''.join(c for c in url if ord(c) >= 32)
        
        return url if is_valid_url(url) else None
    except Exception as e:
        print(f"URL sanitization error: {e}")
        return None

def extract_path_id(stream_link):
    """Extract numeric ID from URL path (e.g., 190029 from .../190029/...)"""
    try:
        if not stream_link:
            return None
            
        # Split URL into parts
        parts = stream_link.split('/')
        
        # Find the numeric part in the path
        for part in parts:
            if part.isdigit():
                return part
                
        return None
    except:
        return None

def format_download_link(stream_link):
    """Generate download URL using ID from path"""
    try:
        if not stream_link:
            raise ValueError("Empty stream link")
            
        stream_link = sanitize_url(stream_link)
        if not stream_link:
            raise ValueError("Invalid URL after sanitization")
            
        # If already in correct format, return as is
        if 'tvplus.app.br/movie/' in stream_link and stream_link.endswith('.mp4'):
            return stream_link
            
        # Get numeric ID from path
        file_id = extract_path_id(stream_link) or str(int(time.time()))
        
        # Construct final URL
        final_url = f"http://tvplus.app.br/movie/{file_id}.mp4"
        
        if not is_valid_url(final_url):
            raise ValueError("Invalid final URL")
            
        return final_url
    except Exception as e:
        print(f"URL formatting error: {e}")
        return None

def remove_extension(filename):
    """Remove .mp4 or other extensions from filename"""
    try:
        if not filename:
            return ""
        return os.path.splitext(filename)[0]
    except:
        return filename

def save_to_series_file(file_name, download_url):
    """Save to series.txt with cleaned filename"""
    try:
        clean_name = remove_extension(file_name)
        with open("Filmes.txt", "a", encoding="utf-8") as f:
            f.write(f"ID: {clean_name}\n")
            f.write(f"Link: {download_url}\n")
            f.write("")  # Add empty line between entries
    except Exception as e:
        print(f"Error saving to series.txt: {e}")

@StreamBot.on_message(
    filters.private
    & (
        filters.document
        | filters.video
        | filters.audio
        | filters.animation
        | filters.voice
        | filters.video_note
        | filters.photo
        | filters.sticker
    ),
    group=4,
)
async def private_receive_handler(c: Client, m: Message):
    try:
        # Forward to log channel
        log_msg = await m.forward(chat_id=Var.BIN_CHANNEL)
        
        # Generate initial links
        _, _, stream_link = await gen_link(m=m, log_msg=log_msg, from_channel=False)
        
        # Get file info
        file_attr = getattr(m, m.media.value)
        file_name = getattr(file_attr, 'file_name', "")
        file_size = getattr(file_attr, 'file_size', 0)
        human_size = f"{round(file_size/(1024*1024), 2)} MB" if file_size else "Unknown"
        
        # Create download URL
        download_url = format_download_link(stream_link) or "http://tvplus.app.br/movie/default.mp4"
        
        # Save to series.txt
        save_to_series_file(file_name, download_url)
        
        # Create minimal message text (with original filename including extension)
        message_text = f"""<b>File Name:</b> <code>{file_name or 'Unnamed File'}</code>
<b>File Size:</b> <code>{human_size}</code>
<b>Download:</b> <code>{download_url}</code>"""

        # Send log message
        await log_msg.reply_text(
            text=f"**Request from:** [{m.from_user.first_name}](tg://user?id={m.from_user.id})\n"
                 f"**User ID:** `{m.from_user.id}`\n"
                 f"**File:** `{file_name}`\n"
                 f"**Size:** `{human_size}`\n"
                 f"**Download:** {download_url}",
            disable_web_page_preview=True,
            parse_mode=ParseMode.MARKDOWN,
            quote=True
        )

        # Send to user
        await m.reply_text(
            text=message_text,
            parse_mode=ParseMode.HTML,
            disable_web_page_preview=True,
            quote=True
        )

    except FloodWait as e:
        print(f"Flood wait: {e.value}s")
        await asyncio.sleep(e.value)
    except Exception as e:
        print(f"Error in handler: {str(e)}", exc_info=True)
        await m.reply_text(
            "⚠️ Error generating links. Please try again later.",
            quote=True
        )
        await c.send_message(
            chat_id=Var.BIN_CHANNEL,
            text=f"🚨 Error processing file:\nUser: {m.from_user.id}\nError: {str(e)}",
            disable_web_page_preview=True
        )