import re
import asyncio
import os
import random 
import time
import hashlib
import subprocess
from telethon import TelegramClient, events, errors
import config  
from insta_handler import upload_to_instagram, upload_story
from text_to_image import create_text_album, create_native_story  
from x_handler import post_to_x

# --- SETUP ---
client = TelegramClient(config.SESSION_NAME, config.API_ID, config.API_HASH, auto_reconnect=True)

# --- STATE: MESSAGE IDs ---
HISTORY_FILE = "router_history.txt"
album_buffer = {}       
processed_ids = set()   
if os.path.exists(HISTORY_FILE):
    with open(HISTORY_FILE, "r") as f:
        processed_ids = set(line.strip() for line in f if line.strip())

def save_id(unique_id):
    with open(HISTORY_FILE, "a") as f: f.write(f"{unique_id}\n")

# --- STATE: TEXT FINGERPRINTS (DEDUPLICATION) ---
HASH_FILE = "content_hashes.txt"
processed_hashes = set()
if os.path.exists(HASH_FILE):
    with open(HASH_FILE, "r") as f:
        processed_hashes = set(line.strip() for line in f if line.strip())

def save_hash(text_hash):
    with open(HASH_FILE, "a") as f: f.write(f"{text_hash}\n")

# --- CLEANING LOGIC ---
FORBIDDEN_WORDS = [
    "تبلیغ", "کازینو", "bet", "crypto", "vpn", "VPN",
    "فیلترشکن", "فیلتر شکن", "سرور اختصاصی", "زگیل تناسلی",
    "قمار", "ChatGPT", "Canva", "پروستات", "کبدچرب", "گوارشی", "ویزا", "اشتراک","کانفیگ","فیلتر","گیگ","تومن"
]
REPLACEMENTS = {
    "@VahidOOnLine":"","@VahidOOnLine":"","@VahidHeadline":"", "Vahid": "", "sentdefender": "", "visegrad24": "",
    "Mojtabapacino": "", "rt_rtiy": "", "✍🏻 adolf hitler": "", "✍🏻 a.tirandaz": "",
    "✍🏻 Nadershah": "", "✍🏻 BOSS": "", "✍🏻 exxon": "", "📝 adolf hitler ": "",
    "✍🏻 𝑻𝑲𝑴":"", "✍🏻 𝑺𝑨𝑹𝑫𝑨𝑹⁪⁬⁮⁮":"", "📝 CAPITANO":"", "✍🏻 Niko":"","✍🏻 CAPITANO":"",
    "NewshaSaremi":"", "✍🏻 BLACK WOLF":"", "✍ Anarchist":"", "✍🏻 ARTEMIS":"","📡 @Online":"",
    "✍🏻  a.tirandaz":"", "✍🏻  Cybex":"", "✍🏻 Cybex":"", "ShahedAlavi":"","📝pajouhesh":"",
    "@VahidHeadline":"", "✍🏻 BOBOOL":"", "▪️ @WARS_NEWS":"","✍🏻 Hitman":"","@WARS_NEWS":"","✍🏻satar khan":"","Hitman":"",
    "✍️satar khan":"","✍🏻 Dangerman":"","hitler":"","وحید":"پاشا","@AQSA_STORN":""
}
HASHTAG_POOL = [
    "#خبر_تحلیلی", "#تحلیل_روز", "#پشت_پرده_سیاسی", "#گزارش_ویژه",
    "#روایت_میدان", "#تحولات_منطقه", "#نبض_خاورمیانه", "#معادلات_قدرت",
    "#اتاق_فکر", "#برآورد_امنیتی", "#موازنه_قوا", "#سناریو_سیاسی",
    "#آینده_ایران", "#تصمیم_بزرگ", "#پیام_سیاسی", "#هشدار_امنیتی",
    "#گسل_سیاسی", "#نقطه_عطف", "#قبل_از_وقوع"
]

def clean_text(text):
    if not text: return None
    text_lower = text.lower()
    for bad_word in FORBIDDEN_WORDS:
        if bad_word.lower() in text_lower:
            print(f"⛔ Blocked Forbidden Word: {bad_word}")
            return None 

    text = re.sub(r'https?://\S+', '', text)
    text = re.sub(r'\S*@\S*', '', text)
    text = re.sub(r'📡\S*', '', text)
    text = re.sub(r'✍🏻 \S*', '', text)

    sorted_replacements = sorted(REPLACEMENTS.keys(), key=len, reverse=True)
    for target in sorted_replacements:
        replacement = REPLACEMENTS[target]
        pattern = re.compile(re.escape(target), re.IGNORECASE)
        text = pattern.sub(replacement, text)

    lines = text.split('\n')
    cleaned_lines = []
    for line in lines:
        line = line.strip()
        if not line: continue
        if line.startswith('@') and len(line.split()) == 1:
            continue
        cleaned_lines.append(line)
    
    final_text = "\n".join(cleaned_lines).strip()
    if not final_text: return None
    return final_text

# --- FFMPEG VIDEO FIXER ---
def fix_video_for_instagram(input_path):
    # If it's a photo, just return it untouched
    if not input_path.lower().endswith(('.mp4', '.mov')):
        return input_path
        
    output_path = input_path.rsplit('.', 1)[0] + "_fixed.mp4"
    print("   ⚙️ Fixing video codec for Instagram (FFmpeg)...")
    try:
        cmd = [
            "ffmpeg", "-y", "-i", input_path,
            "-c:v", "libx264", "-preset", "fast", "-profile:v", "main",
            "-c:a", "aac", "-pix_fmt", "yuv420p",
            output_path
        ]
        subprocess.run(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, check=True)
        return output_path
    except Exception as e:
        print(f"   ⚠️ FFmpeg failed, trying original video: {e}")
        return input_path

# --- PROCESSING ---
async def process_event(event_message, settings):
    msg_id = event_message.id
    chat_id = event_message.chat_id
    unique_msg_id = f"{chat_id}_{msg_id}"
    
    if unique_msg_id in processed_ids: return

    gid = event_message.grouped_id
    if gid and gid in album_buffer:
        album_buffer[gid].append(event_message)
        print(f"   📥 Buffered Additional Part for Group {gid}")
        return

    raw = event_message.text or ""
    cleaned = clean_text(raw)
    
    if not cleaned:
        print("⛔ No valid text found. Skipping.")
        return

    text_fingerprint = hashlib.md5(cleaned.encode('utf-8')).hexdigest()
    
    if text_fingerprint in processed_hashes:
        print("⏩ Duplicate Content Detected. Skipping.")
        return
        
    processed_hashes.add(text_fingerprint)
    save_hash(text_fingerprint)
    
    processed_ids.add(unique_msg_id)
    save_id(unique_msg_id)

    signature = settings.get('signature', "")
    tags = " ".join(random.sample(HASHTAG_POOL, 5))
    caption = f"{cleaned}{signature}\n\n{tags}"

    if len(caption) > 1024:
        caption = caption[:1020] + "..."

    if event_message.grouped_id:
        gid = event_message.grouped_id
        if gid not in album_buffer:
            album_buffer[gid] = []
            asyncio.create_task(process_album(gid, caption, settings))
        album_buffer[gid].append(event_message)
        print(f"   📥 Buffered Part for Group {gid}")
        return 
        
    else:
        target_id = settings['target_telegram_id'] 
        token = settings.get('access_token')        
        uid = settings.get('ig_user_id')            

        try:
            await client.send_message(target_id, caption, file=event_message.media)
            print(f"✅ Sent to Target Channel {target_id}")
        except Exception as e: print(f"❌ TG Error: {e}")

        if token:
            # --- BLOCK 1: NATIVE MEDIA (Photos/Videos) -> INSTA FEED ---
            if event_message.media:
                path = await client.download_media(event_message)
                
                # 1. X GOES FIRST (Uses original file)
                print("   ➡️ Uploading Native Media to X (Twitter)...")
                await asyncio.shield(asyncio.to_thread(post_to_x, caption, path))
                
                # 2. FIX VIDEO CODEC (Photos pass through instantly)
                fixed_path = await asyncio.to_thread(fix_video_for_instagram, path)

                # 3. INSTAGRAM GOES SECOND (Uses the fixed file)
                print("   ➡️ Uploading Native Media to Instagram...")
                await asyncio.shield(asyncio.to_thread(upload_to_instagram, fixed_path, caption, token, uid))

                # Clean up the extra video file
                if fixed_path != path:
                    try: os.remove(fixed_path)
                    except: pass
                
            # --- BLOCK 2: TEXT ONLY -> INSTA STORY ONLY ---
            else:
                print("   📝 Text-only post detected. Converting to images...")
                generated_images = create_text_album(cleaned) 
                story_image = create_native_story(cleaned)
                
                if generated_images:
                    # 1. X GOES FIRST
                    print("   ➡️ Uploading to X (Twitter)...")
                    await asyncio.shield(asyncio.to_thread(post_to_x, caption, generated_images[0]))

                    # 2. INSTAGRAM STORY GOES SECOND
                    if story_image:
                        print("   ➡️ Uploading Text Image to Instagram Story...")
                        await asyncio.shield(asyncio.to_thread(upload_story, story_image, token, uid))
                        try: os.remove(story_image)
                        except: pass

async def process_album(gid, caption, settings):
    await asyncio.sleep(5)
    msgs = album_buffer.pop(gid, [])
    if not msgs: return
    msgs.sort(key=lambda x: x.id)
    
    target_id = settings['target_telegram_id'] 
    token = settings.get('access_token')       
    uid = settings.get('ig_user_id')           

    try:
        media = [m.media for m in msgs]
        await client.send_message(target_id, caption, file=media)
        print(f"✅ Album Sent to {target_id}")
    except Exception as e: print(f"❌ TG Album Error: {e}")

    if token:
        paths = []
        for m in msgs:
            p = await client.download_media(m)
            paths.append(p)
        await asyncio.shield(asyncio.to_thread(upload_to_instagram, paths, caption, token, uid))

@client.on(events.NewMessage(chats=config.SOURCE_CHANNELS))
async def handler(event):
    channel_id = event.chat_id
    settings = config.CHANNEL_MAP.get(channel_id)
    if settings:
        await process_event(event.message, settings)

async def main():
    print(f"🌍 Router Bot Listening on {len(config.SOURCE_CHANNELS)} Channels...")
    while True:
        try:
            await client.start()
            await client.run_until_disconnected()
        except (errors.RPCError, ConnectionError, OSError) as e:
            print(f"⚠️ Network Fluctuation: {e}")
            print("🔄 Reconnecting in 5 seconds...")
            await asyncio.sleep(5) 
        except Exception as e:
            print(f"❌ Critical Error: {e}")
            print("🔄 Restarting bot in 5 seconds...")
            await asyncio.sleep(5) 

if __name__ == '__main__':
    asyncio.run(main())
