#!/usr/bin/env python3
import logging
import requests
import os
import time
import numpy as np
from sentence_transformers import SentenceTransformer
from sklearn.metrics.pairwise import cosine_similarity
from telegram import Update, InlineKeyboardButton, InlineKeyboardMarkup
from telegram.ext import Application, CommandHandler, MessageHandler, filters, ContextTypes, CallbackQueryHandler

# SOZLAMALAR
TELEGRAM_TOKEN = "8345994145:AAH6C9YJmgdOdlCRGrzEkpajd92fZ0H2Myg"
ADMIN_ID = "5997455491"
OLLAMA_URL = "http://localhost:11434/api/generate"
MODEL_NAME = "tinyllama"
KNOWLEDGE_FILE = "bilimlar_bazasi.txt"

logging.basicConfig(
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
    level=logging.INFO
)
logger = logging.getLogger(__name__)

# GLOBAL O'ZGARUVCHILAR
sections = {}
knowledge_chunks = []  # Matn parchalari
chunk_embeddings = None  # Vector embeddings
embedding_model = None  # Sentence Transformer model

# EMBEDDING MODELNI YUKLASH
def load_embedding_model():
    """Sentence Transformer modelini yuklash"""
    global embedding_model
    
    try:
        logger.info("🧠 Vector qidiruv modeli yuklanmoqda...")
        # Kichik va tez model (russo tilini ham tushunadi)
        embedding_model = SentenceTransformer('paraphrase-multilingual-MiniLM-L12-v2')
        logger.info("✅ Vector model yuklandi!")
        return True
    except Exception as e:
        logger.error(f"❌ Model yuklashda xato: {e}")
        logger.info("💡 O'rnatish: pip install sentence-transformers")
        return False

# BILIMLAR BAZASINI YUKLASH
def load_knowledge_base():
    """Bilimlar bazasini yuklash va vectorlash"""
    global sections, knowledge_chunks, chunk_embeddings
    
    try:
        logger.info("📚 Bilimlar bazasi yuklanmoqda...")
        
        with open(KNOWLEDGE_FILE, "r", encoding="utf-8") as f:
            knowledge_base = f.read()
        
        sections = {}
        current_section = "umumiy"
        current_content = []
        
        for line in knowledge_base.split('\n'):
            if line.startswith('# '):
                if current_content:
                    sections[current_section] = '\n'.join(current_content)
                current_section = line.replace('# ', '').strip().lower()
                current_content = [line]
            else:
                current_content.append(line)
        
        if current_content:
            sections[current_section] = '\n'.join(current_content)
        
        logger.info(f"✅ {len(sections)} ta bo'lim yuklandi")
        
        # Matnni parchalarga bo'lish
        knowledge_chunks = []
        for section_name, section_content in sections.items():
            lines = [l.strip() for l in section_content.split('\n') if l.strip() and not l.startswith('#')]
            knowledge_chunks.extend(lines)
        
        logger.info(f"📝 {len(knowledge_chunks)} ta matn parchasi yaratildi")
        
        # Vector embeddings yaratish
        if embedding_model and knowledge_chunks:
            logger.info("🔢 Vectorlar yaratilmoqda...")
            chunk_embeddings = embedding_model.encode(knowledge_chunks, show_progress_bar=False)
            logger.info(f"✅ {len(chunk_embeddings)} ta vector yaratildi!")
        
        return True
        
    except Exception as e:
        logger.error(f"❌ Yuklashda xato: {e}")
        return False

# VECTOR QIDIRUV
def vector_search(query: str, top_k: int = 3) -> str:
    """Semantic search orqali eng mos javobni topish"""
    
    if embedding_model is None or chunk_embeddings is None:
        logger.warning("⚠️ Vector model mavjud emas")
        return None
    
    try:
        # Savolni vectorga aylantirish
        query_embedding = embedding_model.encode([query])[0]
        
        # Cosine similarity hisoblash
        similarities = cosine_similarity([query_embedding], chunk_embeddings)[0]
        
        # Eng yaxshi natijalarni olish
        top_indices = np.argsort(similarities)[-top_k:][::-1]
        
        # Minimal similarity threshold (0.3 dan past bo'lsa rad etish)
        if similarities[top_indices[0]] < 0.3:
            logger.info(f"⚠️ Juda past similarity: {similarities[top_indices[0]]:.2f}")
            return None
        
        # Eng mos javoblarni birlashtirish
        results = []
        for idx in top_indices:
            if similarities[idx] > 0.25:  # Faqat yaxshi natijalar
                results.append(knowledge_chunks[idx])
                logger.info(f"📊 Match: {similarities[idx]:.2f} - {knowledge_chunks[idx][:50]}...")
        
        if results:
            return '\n'.join(results[:2])  # Eng yaxshi 2 ta javob
        
        return None
        
    except Exception as e:
        logger.error(f"❌ Vector qidiruvda xato: {e}")
        return None

# AI JAVOB
def get_ai_response(query: str) -> str:
    """AI orqali javob olish"""
    
    # 1. Vector qidiruvni sinash (eng yaxshisi!)
    vector_answer = vector_search(query)
    if vector_answer:
        logger.info("✅ Vector qidiruvdan topildi!")
        return vector_answer
    
    # 2. Agar topilmasa, AI'ga murojaat
    try:
        relevant_context = find_relevant_sections(query)
        
        prompt = f"""Context: {relevant_context}

Question: {query}

Answer in Uzbek language (short, 2-3 sentences max):"""

        logger.info("🤖 TinyLlama'ga so'rov...")
        
        response = requests.post(
            OLLAMA_URL,
            json={
                "model": MODEL_NAME,
                "prompt": prompt,
                "stream": False,
                "temperature": 0.3,
                "num_predict": 100,
                "stop": ["\n\n", "Question:", "Context:"],
            },
            timeout=30
        )
        
        if response.status_code == 200:
            result = response.json()
            answer = result.get("response", "").strip()
            
            logger.info(f"AI javobi: {answer[:100]}")
            
            answer = answer.split('\n')[0]
            
            # Javobni tekshirish
            invalid_phrases = [
                "i don't", "sorry", "i am", "i can't", 
                "respuesta", "question", "context",
                "the answer", "based on"
            ]
            
            has_invalid = any(phrase in answer.lower() for phrase in invalid_phrases)
            is_too_short = len(answer) < 10
            has_cyrillic = any('\u0400' <= c <= '\u04FF' or '\u0410' <= c <= '\u044F' for c in answer)
            
            if has_invalid or is_too_short or not has_cyrillic:
                logger.warning("⚠️ Javob yaroqsiz yoki noto'g'ri tilda")
                return "TOPILMADI"
            
            return answer[:300]
        else:
            logger.error(f"❌ Ollama xatosi: {response.status_code}")
            return "TOPILMADI"
            
    except Exception as e:
        logger.error(f"❌ Xato: {e}")
        return "TOPILMADI"

# TEGISHLI BO'LIMNI TOPISH (fallback)
def find_relevant_sections(query: str) -> str:
    query_lower = query.lower()
    
    keywords_map = {
        'rahbariyat': ['hokim', 'rahbar', 'qabul'],
        'kommunal': ['elektr', 'gaz', 'suv'],
        'yer': ['yer', 'kadastr'],
        'ijtimoiy': ['daftar', 'subsidiya'],
        'kontakt': ['telefon', 'bog\'lan', 'manzil'],
    }
    
    relevant_sections = []
    
    for category, keywords in keywords_map.items():
        for keyword in keywords:
            if keyword in query_lower:
                for section_name, section_content in sections.items():
                    if category in section_name:
                        if section_content not in relevant_sections:
                            relevant_sections.append(section_content)
    
    if not relevant_sections:
        relevant_sections = list(sections.values())
    
    result = '\n\n'.join(relevant_sections[:1])
    return result[:500]

# ADMINGA XABAR YUBORISH
async def send_to_admin(context: ContextTypes.DEFAULT_TYPE, user, question: str):
    """Topilmagan savolni adminga yuborish"""
    try:
        report = (
            "❓ <b>Javob topilmadi</b>\n\n"
            f"👤 <b>Foydalanuvchi:</b> {user.full_name}\n"
            f"🆔 <b>ID:</b> <code>{user.id}</code>\n"
            f"📝 <b>Savol:</b> {question}\n\n"
            f"⏰ <b>Vaqt:</b> {time.strftime('%d.%m.%Y %H:%M')}"
        )
        
        await context.bot.send_message(
            chat_id=ADMIN_ID,
            text=report,
            parse_mode='HTML'
        )
        logger.info("📨 Savol adminga yuborildi")
        
    except Exception as e:
        logger.error(f"❌ Adminga yuborishda xato: {e}")

# BOT KOMANDALAR
async def start(update: Update, context: ContextTypes.DEFAULT_TYPE):
    await update.message.reply_text(
        "🏛 <b>Assalomu alaykum!</b>\n\n"
        "Qamashi tumani hokimligining botiga xush kelibsiz.\n\n"
        "🧠 <i>Aqlli qidiruv tizimi bilan jihozlangan</i>\n\n"
        "📌 <b>Masalan:</b>\n"
        "• Hokim bilan uchrashish mumkinmi?\n"
        "• Elektr bilan bog'liq murojaat\n"
        "• Mahallalar haqida\n\n"
        "Savolingizni yuboring! 💬",
        parse_mode='HTML'
    )

async def reload_command(update: Update, context: ContextTypes.DEFAULT_TYPE):
    """Admin: bilimlar bazasini qayta yuklash"""
    user_id = str(update.effective_user.id)
    
    if user_id != ADMIN_ID:
        await update.message.reply_text("❌ Bu buyruq faqat admin uchun!")
        return
    
    await update.message.reply_text("🔄 Bilimlar bazasi qayta yuklanmoqda...")
    
    if load_knowledge_base():
        await update.message.reply_text(
            f"✅ Muvaffaqiyatli yangilandi!\n\n"
            f"📚 {len(sections)} ta bo'lim\n"
            f"📝 {len(knowledge_chunks)} ta matn parchasi\n"
            f"🔢 {len(chunk_embeddings)} ta vector\n"
            f"⏰ {time.strftime('%H:%M:%S')}"
        )
        logger.info("✅ Admin tomonidan qayta yuklandi")
    else:
        await update.message.reply_text("❌ Xatolik yuz berdi!")

async def handle_message(update: Update, context: ContextTypes.DEFAULT_TYPE):
    """Xabarlarni qayta ishlash"""
    user_query = update.message.text
    user = update.effective_user
    
    logger.info(f"❓ Savol: {user.full_name} - {user_query}")
    
    waiting_msg = await update.message.reply_text("🔍 Qidiryapman...")
    answer = get_ai_response(user_query)
    await waiting_msg.delete()

    if "TOPILMADI" in answer.upper():
        await send_to_admin(context, user, user_query)
        
        await update.message.reply_text(
            "😊 Afsuski, menda hozircha bu savol javobi yo'q.\n\n"
            "✅ Ammo tashvish qilmang! Men buni siz uchun o'rganib chiqaman.\n\n"
            "📨 Savolingiz mas'ul xodimlarga yuborildi va "
            "tez orada sizga javob berishadi.\n\n"
            "🙏 Sabr qilganingiz uchun rahmat!"
        )
        
        logger.info("ℹ️ Javob topilmadi, adminga yuborildi")
    else:
        await update.message.reply_text(f"✅ {answer}")
        logger.info(f"✓ Javob yuborildi: {len(answer)} belgi")

async def button_click(update: Update, context: ContextTypes.DEFAULT_TYPE):
    """Tugmalar bosilganda"""
    query = update.callback_query
    await query.answer()
    
    dept_map = {
        'dep_kommunal': "Kommunal xo'jalik",
        'dep_kadastr': "Yer va Kadastr",
        'dep_ijtimoiy': "Ijtimoiy himoya"
    }
    
    chosen_dept = dept_map.get(query.data, "Boshqa")
    user = query.from_user
    question = context.user_data.get('last_question', "Savol")

    report = (
        "📩 <b>Murojaat</b>\n\n"
        f"👤 <b>Foydalanuvchi:</b> {user.full_name}\n"
        f"🆔 <b>ID:</b> <code>{user.id}</code>\n"
        f"📂 <b>Bo'lim:</b> {chosen_dept}\n"
        f"❓ <b>Savol:</b> {question}\n\n"
        f"⏰ <b>Vaqt:</b> {time.strftime('%d.%m.%Y %H:%M')}"
    )
    
    try:
        await context.bot.send_message(
            chat_id=ADMIN_ID,
            text=report,
            parse_mode='HTML'
        )
        await query.edit_message_text(
            f"✅ Murojaatingiz <b>{chosen_dept}</b> bo'limiga yuborildi.\n\n"
            "Tez orada javob olasiz. Rahmat! 🙏",
            parse_mode='HTML'
        )
    except Exception as e:
        logger.error(f"❌ Xatolik: {e}")
        await query.edit_message_text("❌ Xatolik yuz berdi.")

def main():
    """Asosiy funksiya"""
    logger.info("🚀 Bot ishga tushmoqda...")
    
    # Vector modelni yuklash
    if not load_embedding_model():
        logger.warning("⚠️ Vector qidiruv o'chirilgan, oddiy rejimda ishga tushdi")
    
    # Bilimlar bazasini yuklash
    if not load_knowledge_base():
        logger.error("❌ Bot ishga tushmadi!")
        exit(1)
    
    logger.info(f"🤖 Model: {MODEL_NAME}")
    
    application = Application.builder().token(TELEGRAM_TOKEN).build()
    
    application.add_handler(CommandHandler("start", start))
    application.add_handler(CommandHandler("reload", reload_command))
    application.add_handler(MessageHandler(filters.TEXT & ~filters.COMMAND, handle_message))
    application.add_handler(CallbackQueryHandler(button_click))
    
    logger.info("✅ Bot muvaffaqiyatli ishga tushdi!")
    logger.info("💡 /reload - bilimlar bazasini yangilash (admin)")
    
    application.run_polling()

if __name__ == '__main__':
    main()