import asyncio
import logging
from datetime import datetime, timezone, timedelta
import aiomysql

logger = logging.getLogger("proxy_manager")

class ProxyManager:
    def __init__(self, db_pool):
        self.db_pool = db_pool
        self.proxies = []
        self.lock = asyncio.Lock()

    async def load_proxies(self):
        async with self.db_pool.acquire() as conn:
            async with conn.cursor(aiomysql.DictCursor) as cur:
                await cur.execute("""
                    SELECT id, proxy, port, username, password, is_banned, banned_until 
                    FROM proxy
                """)
                self.proxies = await cur.fetchall()
        logger.info(f"Завантажено {len(self.proxies)} проксі")

    async def update_last_checked(self, username: str):
        now = datetime.now(timezone.utc).replace(microsecond=0)
        logger.info(f"Оновлюємо last_checked для проксі username={username} на {now}")
        async with self.db_pool.acquire() as conn:
            async with conn.cursor() as cur:
                await cur.execute(
                    "UPDATE proxy SET last_checked=%s WHERE username=%s",
                    (now, username)
                )
                await conn.commit()

    async def ban_proxy(self, username: str, ban_seconds=600):
        ban_until = datetime.now(timezone.utc).replace(microsecond=0) + timedelta(seconds=ban_seconds)
        async with self.db_pool.acquire() as conn:
            async with conn.cursor() as cur:
                await cur.execute(
                    "UPDATE proxy SET is_banned=1, banned_until=%s WHERE username=%s",
                    (ban_until, username)
                )
                await conn.commit()
        logger.warning(f"Забанено проксі username={username} до {ban_until}")

        async with self.lock:
            for p in self.proxies:
                if p['username'] == username:
                    p['is_banned'] = 1
                    p['banned_until'] = ban_until
                    break

    async def unban_expired_proxies(self):
        now = datetime.now(timezone.utc).replace(microsecond=0)
        async with self.db_pool.acquire() as conn:
            async with conn.cursor() as cur:
                await cur.execute(
                    "UPDATE proxy SET is_banned=0, banned_until=NULL WHERE is_banned=1 AND banned_until <= %s",
                    (now,)
                )
                await conn.commit()
        logger.info("Розбанено всі проксі, у яких закінчився бан")
        await self.load_proxies()

    async def get_proxy(self):
        now = datetime.now(timezone.utc).replace(microsecond=0)
        async with self.lock:
            for p in self.proxies:
                banned_until = p.get("banned_until")
                if banned_until and banned_until.tzinfo is None:
                    banned_until = banned_until.replace(tzinfo=timezone.utc)

                if p["is_banned"] == 0 or (banned_until and banned_until <= now):
                    if p["is_banned"] == 1:
                        p["is_banned"] = 0
                        p["banned_until"] = None

                    logger.info(f"Видаємо проксі username={p['username']} і оновлюємо last_checked")
                    await self.update_last_checked(p["username"])
                    return p  # повертаємо повний словник

        return None

    async def run_periodic_unban(self, interval_sec=300):
        while True:
            try:
                await self.unban_expired_proxies()
            except Exception as e:
                logger.error(f"Помилка в unban_expired_proxies: {e}", exc_info=True)
            await asyncio.sleep(interval_sec)
