import requests
import time
import os
import threading
import http.server
import socketserver
import uuid
from PIL import Image
import config

# --- CONFIGURATION ---
# We will use the NGROK_URL from your config file dynamically
PORT = 8081
BASE_FB_URL = "https://graph.facebook.com/v18.0"

# --- CUSTOM MULTI-THREADED SERVER ---
class ThreadingSimpleServer(socketserver.ThreadingMixIn, socketserver.TCPServer):
    allow_reuse_address = True

class CustomHandler(http.server.SimpleHTTPRequestHandler):
    def do_GET(self):
        # 1. Force correct MIME types for Instagram
        if self.path.endswith(".jpg") or self.path.endswith(".jpeg"):
            self.send_response(200)
            self.send_header("Content-type", "image/jpeg")
        elif self.path.endswith(".mp4"):
            self.send_response(200)
            self.send_header("Content-type", "video/mp4")
        else:
            # Fallback for other files
            super().do_GET()
            return

        # 2. Get file size for Content-Length
        try:
            file_path = os.path.join(os.getcwd(), self.path.lstrip("/"))
            file_size = os.path.getsize(file_path)
            self.send_header("Content-Length", str(file_size))
            self.end_headers()
            
            # 3. Serve the file in chunks
            with open(file_path, 'rb') as f:
                self.copyfile(f, self.wfile)
        except Exception as e:
            pass # Handle disconnects silently

    def log_message(self, format, *args):
        pass  # Silence logs

def start_server():
    """Starts the robust server."""
    try:
        server = ThreadingSimpleServer(("", PORT), CustomHandler)
        print(f"🌍 Robust Web Server running on port {PORT}...")
        server.serve_forever()
    except OSError as e:
        pass # Port already in use, which is fine

# Start server immediately
threading.Thread(target=start_server, daemon=True).start()

# --- HELPER: CLEAN FILENAME ---
def clean_filename(file_path):
    try:
        folder = os.path.dirname(file_path)
        ext = os.path.splitext(file_path)[1]
        new_name = f"{uuid.uuid4().hex[:8]}{ext}"
        new_path = os.path.join(folder, new_name)
        os.rename(file_path, new_path)
        return new_path
    except:
        return file_path

# --- IMAGE PROCESSING ---
def validate_and_resize_image(image_path):
    try:
        img = Image.open(image_path)
        if img.mode != 'RGB':
            img = img.convert('RGB')
        
        width, height = img.size
        ratio = width / height

        # Instagram Ratio: 0.8 (4:5) to 1.91 (1.91:1)
        if 0.8 <= ratio <= 1.91:
            return image_path

        print(f"   ⚠️ Fixing Image Ratio! (Current: {ratio:.2f})")
        new_width, new_height = width, height

        if ratio < 0.8:
            new_width = int(height * 0.8)
        elif ratio > 1.91:
            new_height = int(width / 1.91)
        
        new_img = Image.new("RGB", (new_width, new_height), (0, 0, 0))
        x_offset = (new_width - width) // 2
        y_offset = (new_height - height) // 2
        new_img.paste(img, (x_offset, y_offset))
        
        new_img.save(image_path, quality=95)
        return image_path
    except Exception as e:
        print(f"   ❌ Image Check Failed: {e}")
        return image_path

def get_file_type(file_path):
    ext = os.path.splitext(file_path)[1].lower()
    if ext in ['.mp4', '.mov', '.avi', '.mkv', '.webm']:
        return 'VIDEO'
    return 'IMAGE'

def get_public_url(file_path):
    """Returns the Secure HTTPS URL using Ngrok."""
    filename = os.path.basename(file_path)
    # Dynamically pull the URL from config
    clean_base = config.NGROK_URL.rstrip('/')
    public_url = f"{clean_base}/{filename}"
    print(f"   🔗 Serving (HTTPS): {public_url}")
    return public_url

# --- INSTAGRAM API ---
# UPDATED: Now takes token and user_id as arguments
def create_media_container(file_url, media_type, token, user_id, caption="", is_carousel=False):
    url = f"{BASE_FB_URL}/{user_id}/media"
    payload = {"access_token": token}

    if media_type == 'VIDEO':
        payload['video_url'] = file_url
        payload['media_type'] = 'REELS' # Use REELS instead of VIDEO for better support
    else:
        payload['image_url'] = file_url
    
    if not is_carousel:
        payload["caption"] = caption
    else:
        payload["is_carousel_item"] = True

    try:
        r = requests.post(url, data=payload, timeout=60)
        data = r.json()
        if "id" in data: return data["id"]
        print(f"   ❌ Container Error: {data}")
    except Exception as e:
        print(f"   ❌ Container Exception: {e}")
    return None

# UPDATED: Now takes token and user_id as arguments
def publish_container(creation_id, token, user_id):
    url = f"{BASE_FB_URL}/{user_id}/media_publish"
    payload = {"creation_id": creation_id, "access_token": token}
    try:
        r = requests.post(url, data=payload, timeout=60)
        data = r.json()
        if "id" in data:
            print(f"   🎉 SUCCESS! Post ID: {data['id']}")
            return True
        print(f"   ❌ Publish Error: {data}")
    except:
        return False

# UPDATED: Now takes token as argument
def wait_for_processing(container_id, token):
    url = f"{BASE_FB_URL}/{container_id}"
    params = {"fields": "status_code", "access_token": token}
    
    print("   ⏳ Processing", end="")
    for _ in range(40): 
        try:
            r = requests.get(url, params=params, timeout=10)
            status = r.json().get("status_code", "UNKNOWN")
            if status == "FINISHED":
                print(" Done! ✅")
                return True
            elif status == "ERROR":
                print(" Failed! ❌")
                return False
        except:
            pass
        print(".", end="", flush=True)
        time.sleep(4)
    return False

# --- MAIN UPLOAD FUNCTIONS ---
# UPDATED: Now accepts token and user_id
def upload_single_media(path, caption, token, user_id):
    path = clean_filename(path)
    media_type = get_file_type(path)
    if media_type == 'IMAGE':
        validate_and_resize_image(path)

    public_url = get_public_url(path)
    container_id = create_media_container(public_url, media_type, token, user_id, caption=caption)
    
    if container_id and wait_for_processing(container_id, token):
        publish_container(container_id, token, user_id)
        try: os.remove(path)
        except: pass

# UPDATED: Now accepts token and user_id
def upload_album(paths, caption, token, user_id):
    print(f"   📚 Uploading Album ({len(paths)} items)...")
    
    clean_paths = [clean_filename(p) for p in paths]
    container_ids = []

    for path in clean_paths:
        m_type = get_file_type(path)
        if m_type == 'IMAGE':
            validate_and_resize_image(path)
        
        public_url = get_public_url(path)
        c_id = create_media_container(public_url, m_type, token, user_id, is_carousel=True)
        if c_id:
            container_ids.append(c_id)
    
    if not container_ids: return

    print("   🛑 Waiting for Instagram to download items...")
    valid_children = []
    for cid in container_ids:
        if wait_for_processing(cid, token):
            valid_children.append(cid)
    
    if not valid_children: return

    url = f"{BASE_FB_URL}/{user_id}/media"
    payload = {
        "media_type": "CAROUSEL",
        "caption": caption,
        "children": ",".join(valid_children),
        "access_token": token
    }
    r = requests.post(url, data=payload)
    data = r.json()
    if "id" in data:
        if wait_for_processing(data["id"], token):
            publish_container(data["id"], token, user_id)
            for p in clean_paths:
                try: os.remove(p)
                except: pass
    else:
        print(f"   ❌ Album Creation Error: {data}")

# --- MAIN ENTRY POINT ---
# UPDATED: The entry point now expects the 4 arguments sent by tbot.py
def upload_to_instagram(media, caption, token, user_id):
    print(f"\n🚀 [InstaHandler] Request received.")
    if isinstance(media, list):
        upload_album(media, caption, token, user_id)
    else:
        upload_single_media(media, caption, token, user_id)