import os
import time
import json
import subprocess
import psutil
import shutil
import asyncio
from datetime import datetime
from fastapi import FastAPI, Query
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import FileResponse
from pydantic import BaseModel
from typing import Optional, List
import pymysql
import aiohttp

# ========== SOZLAMALAR ==========
BASE_PATH = "/var/www/html/YUKLABOT"
DOWNLOAD_PATH = f"{BASE_PATH}/downloads"
SETTINGS_PATH = f"{BASE_PATH}/settings.json"
INSTAGRAM_COOKIES = f"{BASE_PATH}/cookies.txt"
YOUTUBE_COOKIES = f"{BASE_PATH}/youtube_cookies.txt"
LOG_FILE_BOT = "/var/log/yuklabot_bot.log"
ADMIN_DIR = f"{BASE_PATH}/admin"
BOT_TOKEN = "8330989431:AAGyw91D_Ezb9hOEvWJtruWRuYISw-SI3XA"

# MySQL sozlamalari
DB_CONFIG = {
    'host': 'localhost',
    'user': 'yuklabot',
    'password': 'sanjarbek2208S@!',
    'database': 'yuklabot',
    'charset': 'utf8mb4',
    'cursorclass': pymysql.cursors.DictCursor
}

# ========== DATABASE ==========
def get_db():
    return pymysql.connect(**DB_CONFIG)

# ========== FASTAPI ==========
app = FastAPI(title="YuklaBot Admin API")

app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

# ========== MODELS ==========
class ChannelCreate(BaseModel):
    channel_id: str
    channel_name: str
    channel_url: str

class BroadcastData(BaseModel):
    message: str
    photo_url: Optional[str] = None
    button_text: Optional[str] = None
    button_url: Optional[str] = None

class SettingsData(BaseModel):
    force_subscribe: bool = True
    welcome_message: str = ""
    subscribe_message: str = ""
    subscribed_message: str = ""
    admin_ids: List[int] = []

# ========== HELPERS ==========
def check_service(service_name):
    try:
        result = subprocess.run(["systemctl", "is-active", service_name], capture_output=True, text=True, timeout=5)
        return result.stdout.strip() == "active"
    except:
        return False

def get_cookie_status(path):
    if os.path.exists(path):
        days = (time.time() - os.path.getmtime(path)) / 86400
        if days < 7:
            return f"✅ Faol ({int(days)} kun)"
        return f"⚠️ Eskirgan ({int(days)} kun)"
    return "❌ Topilmadi"

def load_settings():
    default = {
        "force_subscribe": True,
        "welcome_message": "Xush kelibsiz!",
        "subscribe_message": "Kanallarga obuna bo'ling",
        "subscribed_message": "Rahmat!",
        "admin_ids": [6404701185]
    }
    if os.path.exists(SETTINGS_PATH):
        try:
            with open(SETTINGS_PATH, 'r') as f:
                default.update(json.load(f))
        except:
            pass
    return default

def save_settings(settings):
    with open(SETTINGS_PATH, 'w') as f:
        json.dump(settings, f, indent=2, ensure_ascii=False)

# ========== API ENDPOINTS ==========

@app.get("/api/stats")
async def get_stats():
    conn = get_db()
    cursor = conn.cursor()
    
    cursor.execute("SELECT COUNT(*) as c FROM users")
    total_users = cursor.fetchone()['c']
    
    cursor.execute("SELECT COUNT(*) as c FROM users WHERE DATE(created_at) = CURDATE()")
    today_users = cursor.fetchone()['c']
    
    cursor.execute("SELECT COUNT(*) as c FROM users WHERE is_banned = 0")
    active_users = cursor.fetchone()['c']
    
    cursor.execute("SELECT COUNT(*) as c FROM users WHERE is_banned = 1")
    banned_users = cursor.fetchone()['c']
    
    cursor.execute("SELECT COUNT(*) as c FROM downloads")
    total_downloads = cursor.fetchone()['c']
    
    cursor.execute("SELECT COUNT(*) as c FROM channels WHERE is_active = 1")
    total_channels = cursor.fetchone()['c']
    
    conn.close()
    
    return {
        "total_users": total_users,
        "today_users": today_users,
        "active_users": active_users,
        "banned_users": banned_users,
        "total_downloads": total_downloads,
        "total_channels": total_channels
    }

@app.get("/api/stats/platforms")
async def get_platform_stats():
    conn = get_db()
    cursor = conn.cursor()
    cursor.execute("SELECT platform, COUNT(*) as count FROM downloads GROUP BY platform")
    result = {row['platform']: row['count'] for row in cursor.fetchall() if row['platform']}
    conn.close()
    return result

# Users
@app.get("/api/users")
async def get_users(page: int = 1, limit: int = 20):
    conn = get_db()
    cursor = conn.cursor()
    
    offset = (page - 1) * limit
    cursor.execute("SELECT * FROM users ORDER BY created_at DESC LIMIT %s OFFSET %s", (limit, offset))
    users = cursor.fetchall()
    
    # Convert datetime to string
    for user in users:
        if user.get('created_at'):
            user['created_at'] = user['created_at'].isoformat()
        if user.get('last_active'):
            user['last_active'] = user['last_active'].isoformat()
    
    cursor.execute("SELECT COUNT(*) as c FROM users")
    total = cursor.fetchone()['c']
    
    cursor.execute("SELECT COUNT(*) as c FROM users WHERE is_banned = 0")
    active = cursor.fetchone()['c']
    
    cursor.execute("SELECT COUNT(*) as c FROM users WHERE is_banned = 1")
    banned = cursor.fetchone()['c']
    
    conn.close()
    
    return {"users": users, "total": total, "active": active, "banned": banned}

@app.get("/api/users/recent")
async def get_recent_users():
    conn = get_db()
    cursor = conn.cursor()
    cursor.execute("SELECT * FROM users ORDER BY created_at DESC LIMIT 10")
    users = cursor.fetchall()
    for user in users:
        if user.get('created_at'):
            user['created_at'] = user['created_at'].isoformat()
    conn.close()
    return users

@app.post("/api/users/{user_id}/ban")
async def ban_user(user_id: int):
    conn = get_db()
    cursor = conn.cursor()
    cursor.execute("UPDATE users SET is_banned = 1 WHERE user_id = %s", (user_id,))
    conn.commit()
    conn.close()
    return {"success": True}

@app.post("/api/users/{user_id}/unban")
async def unban_user(user_id: int):
    conn = get_db()
    cursor = conn.cursor()
    cursor.execute("UPDATE users SET is_banned = 0 WHERE user_id = %s", (user_id,))
    conn.commit()
    conn.close()
    return {"success": True}

@app.get("/api/users/export")
async def export_users():
    conn = get_db()
    cursor = conn.cursor()
    cursor.execute("SELECT user_id, username, first_name, last_name, language_code, is_banned, created_at FROM users")
    rows = cursor.fetchall()
    conn.close()
    
    csv = "user_id,username,first_name,last_name,language_code,is_banned,created_at\n"
    for row in rows:
        csv += f"{row['user_id']},{row['username'] or ''},{row['first_name'] or ''},{row['last_name'] or ''},{row['language_code'] or ''},{row['is_banned']},{row['created_at']}\n"
    
    return {"csv": csv}

# Channels
@app.get("/api/channels")
async def get_channels():
    conn = get_db()
    cursor = conn.cursor()
    cursor.execute("SELECT * FROM channels ORDER BY created_at DESC")
    channels = cursor.fetchall()
    for ch in channels:
        if ch.get('created_at'):
            ch['created_at'] = ch['created_at'].isoformat()
    conn.close()
    return channels

@app.post("/api/channels")
async def add_channel(data: ChannelCreate):
    conn = get_db()
    cursor = conn.cursor()
    try:
        cursor.execute(
            "INSERT INTO channels (channel_id, channel_name, channel_url) VALUES (%s, %s, %s)",
            (data.channel_id, data.channel_name, data.channel_url)
        )
        conn.commit()
        return {"success": True}
    except pymysql.IntegrityError:
        return {"success": False, "error": "Kanal allaqachon mavjud"}
    finally:
        conn.close()

@app.post("/api/channels/{channel_id}/toggle")
async def toggle_channel(channel_id: int):
    conn = get_db()
    cursor = conn.cursor()
    cursor.execute("UPDATE channels SET is_active = NOT is_active WHERE id = %s", (channel_id,))
    conn.commit()
    conn.close()
    return {"success": True}

@app.delete("/api/channels/{channel_id}")
async def delete_channel(channel_id: int):
    conn = get_db()
    cursor = conn.cursor()
    cursor.execute("DELETE FROM channels WHERE id = %s", (channel_id,))
    conn.commit()
    conn.close()
    return {"success": True}

# Broadcast
@app.post("/api/broadcast")
async def send_broadcast(data: BroadcastData):
    conn = get_db()
    cursor = conn.cursor()
    cursor.execute("SELECT user_id FROM users WHERE is_banned = 0")
    users = [row['user_id'] for row in cursor.fetchall()]
    conn.close()
    
    sent = 0
    failed = 0
    
    async with aiohttp.ClientSession() as session:
        for user_id in users:
            try:
                if data.photo_url:
                    url = f"https://api.telegram.org/bot{BOT_TOKEN}/sendPhoto"
                    payload = {
                        "chat_id": user_id,
                        "photo": data.photo_url,
                        "caption": data.message,
                        "parse_mode": "HTML"
                    }
                else:
                    url = f"https://api.telegram.org/bot{BOT_TOKEN}/sendMessage"
                    payload = {
                        "chat_id": user_id,
                        "text": data.message,
                        "parse_mode": "HTML"
                    }
                
                if data.button_text and data.button_url:
                    payload["reply_markup"] = json.dumps({
                        "inline_keyboard": [[{"text": data.button_text, "url": data.button_url}]]
                    })
                
                async with session.post(url, json=payload) as resp:
                    if resp.status == 200:
                        sent += 1
                    else:
                        failed += 1
                
                await asyncio.sleep(0.05)
            except:
                failed += 1
    
    return {"success": True, "sent": sent, "failed": failed, "total": len(users)}

# Settings
@app.get("/api/settings")
async def get_settings():
    return load_settings()

@app.post("/api/settings")
async def update_settings(data: SettingsData):
    save_settings(data.dict())
    return {"success": True}

# System
@app.get("/api/system")
async def get_system():
    return {
        "cpu": int(psutil.cpu_percent()),
        "ram": int(psutil.virtual_memory().percent),
        "disk": int(psutil.disk_usage('/').percent)
    }

@app.get("/api/services")
async def get_services():
    return {
        "redis": check_service("redis-server"),
        "bot": check_service("yuklabot"),
        "mysql": check_service("mysql")
    }

@app.get("/api/cookies")
async def get_cookies():
    return {
        "instagram": get_cookie_status(INSTAGRAM_COOKIES),
        "youtube": get_cookie_status(YOUTUBE_COOKIES)
    }

@app.get("/api/logs")
async def get_logs(type: str = "bot"):
    log_file = LOG_FILE_BOT
    try:
        if os.path.exists(log_file):
            result = subprocess.run(["tail", "-100", log_file], capture_output=True, text=True, timeout=5)
            return {"logs": result.stdout}
    except:
        pass
    return {"logs": "Log topilmadi"}

@app.post("/api/service/{service}/restart")
async def restart_service(service: str):
    service_map = {"redis": "redis-server", "bot": "yuklabot", "mysql": "mysql"}
    if service in service_map:
        try:
            subprocess.run(["systemctl", "restart", service_map[service]], timeout=10)
            return {"success": True}
        except:
            pass
    return {"success": False}

@app.post("/api/cleanup")
async def cleanup():
    deleted = 0
    if os.path.exists(DOWNLOAD_PATH):
        for folder in os.listdir(DOWNLOAD_PATH):
            folder_path = os.path.join(DOWNLOAD_PATH, folder)
            if os.path.isdir(folder_path):
                age = time.time() - os.path.getctime(folder_path)
                if age > 3600:
                    shutil.rmtree(folder_path)
                    deleted += 1
    return {"success": True, "deleted": deleted}

@app.post("/api/clear-cache")
async def clear_cache():
    return {"success": True, "cleared": 0}

# Static files
@app.get("/")
async def root():
    return FileResponse(os.path.join(ADMIN_DIR, "index.html"))

@app.get("/{filename}")
async def serve_static(filename: str):
    file_path = os.path.join(ADMIN_DIR, filename)
    if os.path.exists(file_path):
        return FileResponse(file_path)
    return FileResponse(os.path.join(ADMIN_DIR, "index.html"))

# Startup
@app.on_event("startup")
async def startup():
    os.makedirs(ADMIN_DIR, exist_ok=True)
    os.makedirs(DOWNLOAD_PATH, exist_ok=True)
    print("=" * 50)
    print("✅ Admin Panel API (MySQL) ishga tushdi!")
    print("🌐 http://37.60.242.66:8080")
    print("🗄️ Database: MySQL")
    print("=" * 50)

if __name__ == "__main__":
    import uvicorn
    uvicorn.run(app, host="0.0.0.0", port=8080)