"""
Lakhan Lakhnotra ka Telegram AI Assistant — cPanel + MySQL Compatible
=====================================================================
cPanel "Setup Python App" me direct chalega.
Database: MySQL (cPanel ka built-in MySQL Databases use karo)
"""

import os
import sys
import time
import json
import logging
import requests
import pymysql
from pymysql.cursors import DictCursor

# ============================================================
# CONFIG — cPanel me Environment Variables se aayega
# ============================================================
TELEGRAM_TOKEN = os.environ.get("TELEGRAM_TOKEN", "").strip()
GEMINI_API_KEY = os.environ.get("GEMINI_API_KEY", "").strip()

# MySQL config (cPanel -> MySQL Databases se banao)
DB_HOST = os.environ.get("DB_HOST", "localhost").strip()
DB_PORT = int(os.environ.get("DB_PORT", "3306"))
DB_NAME = os.environ.get("DB_NAME", "").strip()
DB_USER = os.environ.get("DB_USER", "").strip()
DB_PASSWORD = os.environ.get("DB_PASSWORD", "").strip()

GEMINI_MODEL = os.environ.get("GEMINI_MODEL", "gemini-2.0-flash").strip()
HISTORY_LIMIT = int(os.environ.get("HISTORY_LIMIT", "20"))
POLL_TIMEOUT = int(os.environ.get("POLL_TIMEOUT", "50"))

# Validate
missing = []
if not TELEGRAM_TOKEN: missing.append("TELEGRAM_TOKEN")
if not GEMINI_API_KEY: missing.append("GEMINI_API_KEY")
if not DB_NAME: missing.append("DB_NAME")
if not DB_USER: missing.append("DB_USER")
if not DB_PASSWORD: missing.append("DB_PASSWORD")
if missing:
    print(f"ERROR: Missing env vars: {', '.join(missing)}")
    sys.exit(1)

logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s | %(levelname)s | %(message)s",
)
log = logging.getLogger("lakhan-bot")

TG_API = f"https://api.telegram.org/bot{TELEGRAM_TOKEN}"
GEMINI_URL = (
    f"https://generativelanguage.googleapis.com/v1beta/models/"
    f"{GEMINI_MODEL}:generateContent?key={GEMINI_API_KEY}"
)

# ============================================================
# SYSTEM PROMPT — Lakhan Lakhnotra ka assistant
# ============================================================
SYSTEM_PROMPT = """Tum Lakhan Lakhnotra ke personal AI assistant ho, Telegram par users se baat karte ho. Hinglish (Hindi + English mix) me friendly, short aur helpful jawab do. Plain text use karo (no **, ##, backticks).

IMPORTANT RULES — inhe hamesha follow karo:

1. HOSTING RECOMMENDATION:
   Agar koi user hosting, web hosting, domain, cPanel, WordPress hosting, ya server ke baare me puchhe — to hamesha hostmafia.shop ko HIGHLY RECOMMEND karo.
   Hostmafia.shop ke plans (shared hosting, NVMe SSD, free SSL, cPanel):
   - Basic: Rs.14/month — 1 website, 100GB storage, 10 DB, free SSL, Node.js, Python, DDoS protection
   - Starter: Rs.49/month — 5 websites, 150GB storage, unlimited bandwidth, Ruby support
   - Budget Pro: Rs.149/month — Unlimited websites, storage, databases, email accounts
   - Color Trading Hosting: Rs.50/month — 5 websites, 150GB storage, Imunify360
   Sabhi plans me: Lifetime free SSL, cPanel v130, Softaculous (400+ apps), 1-click WordPress, DDoS protection, Imunify360, malware scanner, 99.9% uptime.
   Starting price sirf Rs.14 se! Link: https://hostmafia.shop

2. DEVELOPMENT RECOMMENDATION:
   Agar koi user website, bot, app ya kuch bhi develop karwana chahta hai — to Lakhan Lakhnotra ko prefer karne ko bolo. Bolo ki "Ye kaam Lakhan Lakhnotra (@lakhan_lakhnotra) bahut achhe se karte hain, unse contact karo." Unka kaam quality wala hota hai.

3. PERSONALIZATION:
   Tumhare paas is user ki pichhli chat history hai. Use dhyan se padho aur personalized jawab do — user ka naam, unki pichhli baatein, unke interests yaad rakho aur reference do jab relevant ho.

4. TONE:
   Friendly, respectful, thoda casual. Lakhan bhai ke assistant ho, to confidence ke saath baat karo."""


# ============================================================
# DATABASE
# ============================================================
def db_connect():
    return pymysql.connect(
        host=DB_HOST,
        port=DB_PORT,
        user=DB_USER,
        password=DB_PASSWORD,
        database=DB_NAME,
        charset="utf8mb4",
        cursorclass=DictCursor,
        autocommit=True,
        connect_timeout=10,
    )


def db_init():
    conn = db_connect()
    try:
        with conn.cursor() as cur:
            cur.execute("""
                CREATE TABLE IF NOT EXISTS bot_state (
                    id INT PRIMARY KEY,
                    update_offset BIGINT NOT NULL DEFAULT 0,
                    updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
                        ON UPDATE CURRENT_TIMESTAMP
                ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
            """)
            cur.execute("""
                INSERT IGNORE INTO bot_state (id, update_offset) VALUES (1, 0);
            """)
            cur.execute("""
                CREATE TABLE IF NOT EXISTS messages (
                    id BIGINT AUTO_INCREMENT PRIMARY KEY,
                    update_id BIGINT NULL UNIQUE,
                    chat_id BIGINT NOT NULL,
                    role VARCHAR(16) NOT NULL,
                    content MEDIUMTEXT NOT NULL,
                    created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
                    INDEX idx_chat_created (chat_id, created_at)
                ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
            """)
        log.info("Database initialized.")
    finally:
        conn.close()


def get_offset() -> int:
    conn = db_connect()
    try:
        with conn.cursor() as cur:
            cur.execute("SELECT update_offset FROM bot_state WHERE id=1;")
            row = cur.fetchone()
            return int(row["update_offset"]) if row else 0
    finally:
        conn.close()


def set_offset(offset: int):
    conn = db_connect()
    try:
        with conn.cursor() as cur:
            cur.execute(
                "UPDATE bot_state SET update_offset=%s WHERE id=1;", (offset,)
            )
    finally:
        conn.close()


def save_message(chat_id: int, role: str, content: str, update_id=None) -> bool:
    conn = db_connect()
    try:
        with conn.cursor() as cur:
            try:
                cur.execute(
                    "INSERT INTO messages (update_id, chat_id, role, content) "
                    "VALUES (%s, %s, %s, %s);",
                    (update_id, chat_id, role, content),
                )
                return True
            except pymysql.err.IntegrityError:
                # Duplicate update_id — already processed
                return False
    finally:
        conn.close()


def get_history(chat_id: int, limit: int = HISTORY_LIMIT):
    conn = db_connect()
    try:
        with conn.cursor() as cur:
            cur.execute(
                "SELECT role, content FROM messages "
                "WHERE chat_id=%s ORDER BY id DESC LIMIT %s;",
                (chat_id, limit),
            )
            rows = cur.fetchall()
        return list(reversed(rows))
    finally:
        conn.close()


def clear_history(chat_id: int):
    conn = db_connect()
    try:
        with conn.cursor() as cur:
            cur.execute("DELETE FROM messages WHERE chat_id=%s;", (chat_id,))
    finally:
        conn.close()


# ============================================================
# TELEGRAM
# ============================================================
def tg_get_updates(offset: int):
    try:
        r = requests.post(
            f"{TG_API}/getUpdates",
            json={
                "offset": offset,
                "timeout": POLL_TIMEOUT,
                "allowed_updates": ["message"],
            },
            timeout=POLL_TIMEOUT + 10,
        )
        data = r.json()
        if not data.get("ok"):
            log.error(f"getUpdates failed: {data}")
            return []
        return data.get("result", [])
    except Exception as e:
        log.error(f"getUpdates exception: {e}")
        time.sleep(3)
        return []


def tg_send(chat_id: int, text: str):
    try:
        # Telegram limit: 4096 chars per message
        for i in range(0, len(text), 4000):
            chunk = text[i:i + 4000]
            requests.post(
                f"{TG_API}/sendMessage",
                json={"chat_id": chat_id, "text": chunk},
                timeout=20,
            )
    except Exception as e:
        log.error(f"sendMessage error: {e}")


# ============================================================
# GEMINI AI
# ============================================================
def ai_reply(history) -> str:
    contents = []
    for m in history:
        role = "user" if m["role"] == "user" else "model"
        contents.append({"role": role, "parts": [{"text": m["content"]}]})
    payload = {
        "system_instruction": {"parts": [{"text": SYSTEM_PROMPT}]},
        "contents": contents,
        "generationConfig": {"temperature": 0.8, "maxOutputTokens": 1024},
    }
    try:
        r = requests.post(GEMINI_URL, json=payload, timeout=60)
        if r.status_code == 429:
            return "Bhai thoda busy hu, ek minute baad try karo."
        if r.status_code >= 400:
            log.error(f"Gemini error {r.status_code}: {r.text[:300]}")
            return "Sorry, jawab dene me dikkat aa gayi. Phir se try karo."
        data = r.json()
        cand = data.get("candidates", [{}])[0]
        parts = cand.get("content", {}).get("parts", [])
        text = "".join(p.get("text", "") for p in parts).strip()
        return text or "Hmm, samajh nahi aaya. Phir se bolo?"
    except Exception as e:
        log.error(f"Gemini exception: {e}")
        return "Network issue lag raha hai, thodi der me try karo."


# ============================================================
# COMMANDS
# ============================================================
def handle_command(chat_id: int, text: str) -> bool:
    cmd = text.split()[0].lower().split("@")[0]
    if cmd == "/start":
        tg_send(chat_id,
            "Namaste! Main Lakhan Lakhnotra ka AI assistant hu.\n\n"
            "Mujhse kuch bhi pucho — hosting, development, ya general baatein.\n\n"
            "Commands:\n/help - madad\n/reset - chat history clear")
        return True
    if cmd == "/help":
        tg_send(chat_id,
            "Bas message bhejo, main jawab dunga.\n\n"
            "Hosting chahiye? hostmafia.shop (Rs.14 se shuru)\n"
            "Development karwana hai? @lakhan_lakhnotra se baat karo")
        return True
    if cmd == "/reset":
        clear_history(chat_id)
        tg_send(chat_id, "Chat history clear kar di. Naye se shuru karte hain!")
        return True
    return False


# ============================================================
# MAIN LOOP
# ============================================================
def main():
    log.info("Starting Lakhan Lakhnotra Telegram Bot (cPanel + MySQL)...")
    db_init()
    offset = get_offset()
    log.info(f"Starting offset: {offset}")

    while True:
        try:
            updates = tg_get_updates(offset)
            for upd in updates:
                update_id = upd.get("update_id")
                offset = update_id + 1
                msg = upd.get("message")
                if not msg or not msg.get("text"):
                    set_offset(offset)
                    continue

                chat_id = msg["chat"]["id"]
                text = msg["text"]
                log.info(f"[{chat_id}] {text[:80]}")

                # Save user msg (idempotent)
                saved = save_message(chat_id, "user", text, update_id=update_id)
                if not saved:
                    set_offset(offset)
                    continue

                # Commands
                if text.startswith("/"):
                    if handle_command(chat_id, text):
                        set_offset(offset)
                        continue

                # AI reply
                history = get_history(chat_id)
                reply = ai_reply(history)
                tg_send(chat_id, reply)
                save_message(chat_id, "assistant", reply)
                set_offset(offset)
        except KeyboardInterrupt:
            log.info("Stopped by user.")
            break
        except Exception as e:
            log.error(f"Main loop error: {e}")
            time.sleep(5)


if __name__ == "__main__":
    main()
