import os
import io
import sys
import asyncio
import discord
import aiohttp
import pandas as pd
import gradio as gr
from datetime import datetime, timedelta
from discord.ext import commands
from apscheduler.schedulers.asyncio import AsyncIOScheduler

# Environment variable for Discord token
DISCORD_TOKEN = os.environ.get("DISCORD_TOKEN", None)

# Create Discord bot with all intents
intents = discord.Intents.all()
bot = commands.Bot(command_prefix='!', intents=intents)

# Set up an async scheduler for periodic tasks (like a bot restart)
scheduler = AsyncIOScheduler()

def restart_bot():
    print("Restarting bot...")
    os.execv(sys.executable, ['python'] + sys.argv)

@scheduler.scheduled_job('interval', minutes=60)
def periodic_restart():
    print("Scheduled restart triggered...")
    restart_bot()

async def process_row(row, guild, role):
    """
    Process a single CSV row: if the Discord member associated with the row hasn't received the role, add it.
    """
    hf_user_name = row['hf_user_name']
    if pd.notna(hf_user_name) and hf_user_name.lower() != 'n/a':
        discord_id = row['discord_user_id'].strip('L')
        try:
            member = guild.get_member(int(discord_id))
        except Exception as e:
            print(f"Error converting Discord ID {discord_id}: {e}")
            return

        if not member:
            return

        if role not in member.roles:
            try:
                await member.add_roles(role)
                print(f"Role added to member: {member}")
                lunar = bot.get_user(811235357663297546)
                if lunar:
                    await lunar.send(f"Verified role given to {member}!")
                await member.send(
                    f"Verification successful! [{member} <---> {row['discord_user_name']}]"
                )
            except Exception as e:
                print(f"Error processing member {member}: {e}")

async def give_verified_roles():
    """
    Periodically fetch CSV data from Google Sheets and verify roles for members.
    """
    while True:
        try:
            async with aiohttp.ClientSession() as session:
                try:
                    async with session.get(
                        "https://docs.google.com/spreadsheets/d/1C8aLqgCqLYcMiIFf-P_Aosaa03C_WLIB_UyqvjSdWg8/export?format=csv&gid=0",
                        timeout=10
                    ) as response:
                        if response.status != 200:
                            print(f"Failed to fetch CSV: HTTP {response.status}")
                            await asyncio.sleep(30)
                            continue
                        csv_data = await response.text()
                        global_df = pd.read_csv(io.StringIO(csv_data))
                except asyncio.TimeoutError:
                    print("CSV fetch timed out.")
                    await asyncio.sleep(30)
                    continue
                except Exception as e:
                    print(f"Error fetching CSV: {e}")
                    await asyncio.sleep(30)
                    continue

            guild = bot.get_guild(879548962464493619)
            if not guild:
                print("Guild not found.")
                await asyncio.sleep(30)
                continue
            role = guild.get_role(900063512829755413)
            if not role:
                print("Role not found.")
                await asyncio.sleep(30)
                continue

            await guild.chunk()  # Cache all guild members

            tasks = [process_row(row, guild, role) for _, row in global_df.iterrows()]
            await asyncio.gather(*tasks)
        except Exception as e:
            print(f"Error in give_verified_roles loop: {e}")
        await asyncio.sleep(30)  # Adjust the sleep interval as needed

@bot.event
async def on_ready():
    print(f"We have logged in as {bot.user}")
    scheduler.start()
    # Start the background role verification loop
    bot.loop.create_task(give_verified_roles())

def greet(name):
    return "Hello " + name + "!"

# Create the Gradio interface
demo = gr.Interface(fn=greet, inputs="text", outputs="text")

async def main():
    # Launch Gradio in a separate thread (non-blocking) without using the unsupported 'block' parameter
    gradio_thread = asyncio.to_thread(demo.launch, share=False)
    # Run both the Discord bot and Gradio concurrently
    await asyncio.gather(
        bot.start(DISCORD_TOKEN),
        gradio_thread
    )

if __name__ == "__main__":
    try:
        asyncio.run(main())
    except KeyboardInterrupt:
        print("Shutting down...")