#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import os
import sys
import json
import logging
import requests
import signal
import atexit
from datetime import datetime, date, timedelta
from collections import defaultdict
from typing import Dict, List, Optional, Any

# بررسی نسخه پایتون
if sys.version_info < (3, 7):
    print("❌ حداقل پایتون 3.7 نیاز است")
    sys.exit(1)

# بارگذاری کتابخانه‌ها
try:
    from telegram import Update, ReplyKeyboardMarkup, ReplyKeyboardRemove
    from telegram.ext import (
        Updater, CommandHandler, MessageHandler, 
        Filters, CallbackContext, ConversationHandler
    )
    from dotenv import load_dotenv
except ImportError as e:
    print(f"❌ کتابخانه مورد نیاز یافت نشد: {e}")
    print("دستور نصب: pip install python-telegram-bot python-dotenv requests")
    sys.exit(1)

# بارگذاری متغیرهای محیطی
load_dotenv()

# تنظیمات
BOT_TOKEN = os.getenv('BOT_TOKEN')
API_BASE_URL = "https://amlakjame.ir"
ADMIN_IDS = [589435914]  # شناسه ادمین‌ها

# حالت‌های مکالمه
GET_PROVINCE, GET_CITY, ADVANCED_SEARCH, VIEW_LISTINGS = range(4)

# تنظیمات لاگ‌گیری
def setup_logging():
    """تنظیمات پیشرفته لاگ‌گیری"""
    if not os.path.exists('logs'):
        os.makedirs('logs')
    
    # فرمت تاریخ و زمان فارسی
    class PersianTimeFormatter(logging.Formatter):
        def formatTime(self, record, datefmt=None):
            dt = datetime.fromtimestamp(record.created)
            return dt.strftime('%Y-%m-%d %H:%M:%S')
    
    formatter = PersianTimeFormatter(
        '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
    )
    
    # Handler فایل
    file_handler = logging.FileHandler(
        f'logs/bot_{date.today().strftime("%Y%m%d")}.log', 
        encoding='utf-8'
    )
    file_handler.setFormatter(formatter)
    file_handler.setLevel(logging.INFO)
    
    # Handler کنسول
    console_handler = logging.StreamHandler()
    console_handler.setFormatter(formatter)
    console_handler.setLevel(logging.INFO)
    
    # تنظیم لاگر ریشه
    root_logger = logging.getLogger()
    root_logger.setLevel(logging.INFO)
    root_logger.addHandler(file_handler)
    root_logger.addHandler(console_handler)
    
    # کاهش لاگ کتابخانه‌ها
    logging.getLogger('telegram').setLevel(logging.WARNING)
    logging.getLogger('urllib3').setLevel(logging.WARNING)
    logging.getLogger('apscheduler').setLevel(logging.WARNING)
    
    return logging.getLogger(__name__)

logger = setup_logging()

class CacheManager:
    """مدیریت کش برای بهبود عملکرد"""
    
    def __init__(self, ttl=300):  # 5 دقیقه
        self.cache = {}
        self.ttl = ttl
        self.timestamps = {}
    
    def get(self, key):
        """دریافت مقدار از کش"""
        if key in self.cache:
            if datetime.now().timestamp() - self.timestamps[key] < self.ttl:
                return self.cache[key]
            else:
                # حذف آیتم منقضی شده
                del self.cache[key]
                del self.timestamps[key]
        return None
    
    def set(self, key, value):
        """ذخیره مقدار در کش"""
        self.cache[key] = value
        self.timestamps[key] = datetime.now().timestamp()
    
    def clear(self):
        """پاک کردن کش"""
        self.cache.clear()
        self.timestamps.clear()

class APIClient:
    """کلاینت برای ارتباط با API وب‌سایت"""
    
    def __init__(self, base_url):
        self.base_url = base_url
        self.session = requests.Session()
        self.cache = CacheManager()
        
        # تنظیم هدرهای پیش‌فرض
        self.session.headers.update({
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
            'Accept': 'application/json',
            'Accept-Language': 'fa-IR,fa;q=0.9',
            'Referer': base_url
        })
    
    def request(self, endpoint, params=None, method='GET', timeout=15):
        """درخواست به API"""
        cache_key = f"{endpoint}_{json.dumps(params, sort_keys=True) if params else ''}"
        
        # بررسی کش
        cached = self.cache.get(cache_key)
        if cached:
            return cached
        
        url = f"{self.base_url}/{endpoint.lstrip('/')}"
        
        try:
            if method.upper() == 'GET':
                response = self.session.get(url, params=params, timeout=timeout)
            else:
                response = self.session.post(url, json=params, timeout=timeout)
            
            response.raise_for_status()
            data = response.json()
            
            # ذخیره در کش
            self.cache.set(cache_key, data)
            
            return data
            
        except requests.exceptions.Timeout:
            logger.error(f"Timeout در ارتباط با {url}")
            return None
        except requests.exceptions.RequestException as e:
            logger.error(f"خطا در ارتباط با API: {e}")
            return None
        except json.JSONDecodeError:
            logger.error(f"پاسخ JSON نامعتبر از {url}")
            return None
    
    def get_provinces(self):
        """دریافت لیست استان‌ها"""
        endpoints = [
            'realestate/provinces',
            'api/provinces',
            'provinces'
        ]
        
        for endpoint in endpoints:
            data = self.request(endpoint)
            if data:
                # پردازش ساختارهای مختلف پاسخ
                if isinstance(data, list):
                    return data
                elif isinstance(data, dict):
                    for key in ['data', 'provinces', 'items', 'results']:
                        if key in data and isinstance(data[key], list):
                            return data[key]
        
        # لیست پیش‌فرض
        return [
            "آذربایجان شرقی", "آذربایجان غربی", "اردبیل", "اصفهان",
            "البرز", "ایلام", "بوشهر", "تهران", "چهارمحال و بختیاری",
            "خراسان جنوبی", "خراسان رضوی", "خراسان شمالی", "خوزستان",
            "زنجان", "سمنان", "سیستان و بلوچستان", "فارس", "قزوین",
            "قم", "کردستان", "کرمان", "کرمانشاه", "کهگیلویه و بویراحمد",
            "گلستان", "گیلان", "لرستان", "مازندران", "مرکزی",
            "هرمزگان", "همدان", "یزد"
        ]
    
    def get_cities(self, province):
        """دریافت لیست شهرهای یک استان"""
        cache_key = f"cities_{province}"
        cached = self.cache.get(cache_key)
        if cached:
            return cached
        
        endpoints = [
            f'realestate/cities?province={province}',
            f'api/cities?province={province}',
            f'cities?province={province}'
        ]
        
        for endpoint in endpoints:
            data = self.request(endpoint)
            if data:
                cities = []
                
                if isinstance(data, list):
                    cities = data
                elif isinstance(data, dict):
                    for key in ['data', 'cities', 'items', 'results']:
                        if key in data and isinstance(data[key], list):
                            cities = data[key]
                
                if cities:
                    self.cache.set(cache_key, cities)
                    return cities
        
        # لیست پیش‌فرض شهرها
        default_cities = self._get_default_cities(province)
        self.cache.set(cache_key, default_cities)
        return default_cities
    
    def get_listings(self, province, city, property_type=None):
        """دریافت آگهی‌ها"""
        params = {
            'province': province,
            'city': city
        }
        
        # نگاشت نوع ملک
        type_mapping = {
            "فروش خانه / ویلا": "خانه فروشی",
            "اجاره خانه / ویلا": "خانه اجاره ایی",
            "فروش زمین": "فروش زمین",
            "فروش مغازه / واحد تجاری": "فروش مغازه",
            "اجاره مغازه / واحد تجاری": "اجاره مغازه"
        }
        
        if property_type and property_type in type_mapping:
            params['type'] = type_mapping[property_type]
        
        data = self.request('realestate/listings', params=params)
        
        if data and isinstance(data, list):
            return data
        elif data and isinstance(data, dict):
            if data.get('success') and 'data' in data:
                return data['data']
        
        return []
    
    def _get_default_cities(self, province):
        """لیست پیش‌فرض شهرها"""
        cities_map = {
            "تهران": ["تهران", "اسلامشهر", "شهریار", "ری", "ورامین", "پاکدشت"],
            "اصفهان": ["اصفهان", "کاشان", "خمینی شهر", "نجف آباد", "شاهین شهر"],
            "خراسان رضوی": ["مشهد", "نیشابور", "سبزوار", "تربت حیدریه", "قوچان"],
            "فارس": ["شیراز", "مرودشت", "کازرون", "جهرم", "فسا", "لار"],
            "خوزستان": ["اهواز", "آبادان", "خرمشهر", "دزفول", "مسجدسلیمان"],
            "آذربایجان شرقی": ["تبریز", "مراغه", "مرند", "میانه", "اهر"],
            "آذربایجان غربی": ["ارومیه", "خوی", "مهاباد", "بوکان", "ماکو"],
            "کرمان": ["کرمان", "رفسنجان", "سیرجان", "بم", "جیرفت"],
            "گیلان": ["رشت", "انزلی", "لاهیجان", "آستارا", "تالش"],
            "مازندران": ["ساری", "بابل", "آمل", "قائم شهر", "تنکابن"]
        }
        
        return cities_map.get(province, ["مرکز استان"])

class UserStats:
    """مدیریت آمار کاربران"""
    
    def __init__(self, stats_file='logs/user_stats.json'):
        self.stats_file = stats_file
        self.stats = self._load_stats()
        self._lock = False
    
    def _load_stats(self):
        """بارگذاری آمار از فایل با تصحیح ساختار داده"""
        try:
            if os.path.exists(self.stats_file):
                with open(self.stats_file, 'r', encoding='utf-8') as f:
                    data = json.load(f)
                    
                    # تبدیل ساختارهای قدیمی به جدید
                    return self._migrate_stats(data)
                    
        except Exception as e:
            logger.error(f"خطا در بارگذاری آمار: {e}")
        
        # ساختار پیش‌فرض جدید
        return {
            'total_users': 0,
            'active_users': set(),
            'daily_stats': {},
            'user_actions': {},
            'provinces': {},
            'cities': {},
            'total_searches': 0
        }
    
    def _migrate_stats(self, data):
        """مهاجرت ساختارهای قدیمی به جدید"""
        # تبدیل active_users به set
        if 'active_users' in data:
            if isinstance(data['active_users'], list):
                data['active_users'] = set(data['active_users'])
            elif not isinstance(data['active_users'], set):
                data['active_users'] = set()
        else:
            data['active_users'] = set()
        
        # اطمینان از وجود total_users
        if 'total_users' not in data:
            data['total_users'] = len(data['active_users'])
        
        # اطمینان از وجود daily_stats
        if 'daily_stats' not in data:
            data['daily_stats'] = {}
        
        # اطمینان از وجود user_actions
        if 'user_actions' not in data:
            data['user_actions'] = {}
        
        # اطمینان از وجود provinces
        if 'provinces' not in data:
            data['provinces'] = {}
        
        # اطمینان از وجود cities
        if 'cities' not in data:
            data['cities'] = {}
        
        # اطمینان از وجود total_searches
        if 'total_searches' not in data:
            data['total_searches'] = 0
        
        # اصلاح ساختار daily_stats
        for day, day_stats in data['daily_stats'].items():
            # اطمینان از وجود کلیدهای لازم
            required_keys = ['new_users', 'total_actions', 'searches', 'active_users']
            for key in required_keys:
                if key not in day_stats:
                    if key == 'active_users':
                        day_stats[key] = set()
                    else:
                        day_stats[key] = 0
            
            # تبدیل active_users به set اگر list است
            if isinstance(day_stats['active_users'], list):
                day_stats['active_users'] = set(day_stats['active_users'])
        
        return data
    
    def save_stats(self):
        """ذخیره آمار در فایل"""
        if self._lock:
            return
        
        self._lock = True
        try:
            # ایجاد کپی از آمار برای ذخیره
            stats_to_save = self.stats.copy()
            
            # تبدیل setها به list برای ذخیره JSON
            if isinstance(stats_to_save['active_users'], set):
                stats_to_save['active_users'] = list(stats_to_save['active_users'])
            
            # تبدیل setهای داخل daily_stats به list
            for day, day_stats in stats_to_save['daily_stats'].items():
                if 'active_users' in day_stats and isinstance(day_stats['active_users'], set):
                    day_stats['active_users'] = list(day_stats['active_users'])
            
            with open(self.stats_file, 'w', encoding='utf-8') as f:
                json.dump(stats_to_save, f, ensure_ascii=False, indent=2)
                
        except Exception as e:
            logger.error(f"خطا در ذخیره آمار: {e}")
        finally:
            self._lock = False
    
    def track_user(self, user_id: int, username: str, action: str, **kwargs):
        """رهگیری فعالیت کاربر"""
        today = date.today().isoformat()
        user_key = str(user_id)
        
        # مقداردهی اولیه آمار روزانه
        if today not in self.stats['daily_stats']:
            self.stats['daily_stats'][today] = {
                'new_users': 0,
                'total_actions': 0,
                'searches': 0,
                'active_users': set()
            }
        
        # اطمینان از وجود کلیدهای لازم در daily_stats امروز
        daily_today = self.stats['daily_stats'][today]
        if 'active_users' not in daily_today:
            daily_today['active_users'] = set()
        if 'new_users' not in daily_today:
            daily_today['new_users'] = 0
        if 'total_actions' not in daily_today:
            daily_today['total_actions'] = 0
        if 'searches' not in daily_today:
            daily_today['searches'] = 0
        
        # ثبت کاربر جدید
        if user_key not in self.stats['active_users']:
            self.stats['active_users'].add(user_key)
            self.stats['total_users'] = len(self.stats['active_users'])
            daily_today['new_users'] += 1
        
        # افزودن به کاربران فعال روز
        daily_today['active_users'].add(user_key)
        daily_today['total_actions'] += 1
        
        # ثبت اطلاعات کاربر
        if user_key not in self.stats['user_actions']:
            self.stats['user_actions'][user_key] = {
                'username': username or f"user_{user_id}",
                'first_seen': datetime.now().isoformat(),
                'last_seen': datetime.now().isoformat(),
                'total_actions': 0,
                'last_action': action,
                'last_province': kwargs.get('province'),
                'last_city': kwargs.get('city')
            }
        
        # به‌روزرسانی اطلاعات کاربر
        user_data = self.stats['user_actions'][user_key]
        user_data['last_seen'] = datetime.now().isoformat()
        user_data['total_actions'] += 1
        user_data['last_action'] = action
        user_data['last_province'] = kwargs.get('province')
        user_data['last_city'] = kwargs.get('city')
        
        # آمار ویژه برای جستجوها
        if action == 'search':
            daily_today['searches'] += 1
            self.stats['total_searches'] += 1
            
            province = kwargs.get('province')
            city = kwargs.get('city')
            
            if province:
                self.stats['provinces'][province] = self.stats['provinces'].get(province, 0) + 1
            if city:
                self.stats['cities'][city] = self.stats['cities'].get(city, 0) + 1
        
        # ذخیره آمار
        self.save_stats()
    
    def get_stats_summary(self):
        """دریافت خلاصه آمار"""
        today = date.today().isoformat()
        
        # آمار امروز با مقدار پیش‌فرض
        today_stats = self.stats['daily_stats'].get(today, {
            'new_users': 0,
            'total_actions': 0,
            'searches': 0,
            'active_users': set()
        })
        
        # محاسبه آمار هفته جاری
        week_ago = (date.today() - timedelta(days=7)).isoformat()
        weekly_stats = {
            'new_users': 0,
            'total_actions': 0,
            'searches': 0,
            'active_users': set()
        }
        
        for day, day_stats in self.stats['daily_stats'].items():
            if day >= week_ago:
                weekly_stats['new_users'] += day_stats.get('new_users', 0)
                weekly_stats['total_actions'] += day_stats.get('total_actions', 0)
                weekly_stats['searches'] += day_stats.get('searches', 0)
                
                # جمع‌آوری کاربران فعال هفته
                active_users = day_stats.get('active_users', set())
                if isinstance(active_users, list):
                    weekly_stats['active_users'].update(set(active_users))
                elif isinstance(active_users, set):
                    weekly_stats['active_users'].update(active_users)
        
        # محبوب‌ترین استان‌ها و شهرها
        top_provinces = sorted(
            self.stats['provinces'].items(), 
            key=lambda x: x[1], 
            reverse=True
        )[:5]
        
        top_cities = sorted(
            self.stats['cities'].items(), 
            key=lambda x: x[1], 
            reverse=True
        )[:5]
        
        return {
            'total_users': self.stats['total_users'],
            'today_new_users': today_stats.get('new_users', 0),
            'today_actions': today_stats.get('total_actions', 0),
            'today_searches': today_stats.get('searches', 0),
            'weekly_new_users': weekly_stats['new_users'],
            'weekly_actions': weekly_stats['total_actions'],
            'weekly_searches': weekly_stats['searches'],
            'weekly_active_users': len(weekly_stats['active_users']),
            'total_searches': self.stats['total_searches'],
            'top_provinces': top_provinces,
            'top_cities': top_cities
        }

class AmlakJameBot:
    """کلاس اصلی ربات"""
    
    def __init__(self):
        self.api_client = APIClient(API_BASE_URL)
        self.user_stats = UserStats()
        self.user_sessions = {}  # ذخیره سشن‌های کاربران
        self.cache = CacheManager(ttl=1800)  # 30 دقیقه
        
    def _get_user_session(self, user_id):
        """دریافت یا ایجاد سشن کاربر"""
        if user_id not in self.user_sessions:
            self.user_sessions[user_id] = {
                'current_page': 0,
                'selected_province': None,
                'selected_city': None,
                'selected_type': None,
                'listings': [],
                'city_page': 0
            }
        
        # پاک کردن سشن‌های قدیمی (بیش از 1 ساعت)
        to_delete = []
        for uid, session in self.user_sessions.items():
            if 'last_active' in session:
                if (datetime.now() - session['last_active']).seconds > 3600:
                    to_delete.append(uid)
        
        for uid in to_delete:
            del self.user_sessions[uid]
        
        self.user_sessions[user_id]['last_active'] = datetime.now()
        return self.user_sessions[user_id]
    
    def _clear_user_session(self, user_id):
        """پاک کردن سشن کاربر"""
        if user_id in self.user_sessions:
            del self.user_sessions[user_id]
    
    def start(self, update: Update, context: CallbackContext) -> int:
        """شروع ربات"""
        user = update.effective_user
        
        # پاک کردن سشن قبلی
        self._clear_user_session(user.id)
        context.user_data.clear()
        
        # رهگیری کاربر با try-except برای خطاهای احتمالی
        try:
            self.user_stats.track_user(
                user.id, 
                user.username, 
                'start'
            )
        except Exception as e:
            logger.error(f"خطا در رهگیری کاربر: {e}")
            # ادامه می‌دهیم حتی اگر رهگیری با خطا مواجه شد
        
        # ایجاد کیبورد استان‌ها
        keyboard = self._create_provinces_keyboard()
        
        update.message.reply_text(
            "🏠 به ربات املاک جامع خوش آمدید!\n\n"
            "🏙️ لطفاً استان مورد نظر خود را انتخاب کنید:",
            reply_markup=keyboard
        )
        
        return GET_PROVINCE
    
    def _create_provinces_keyboard(self):
        """ایجاد کیبورد استان‌ها"""
        provinces = self.api_client.get_provinces()
        
        if not provinces:
            provinces = [
                "تهران", "اصفهان", "خراسان رضوی", "فارس", "خوزستان",
                "آذربایجان شرقی", "گیلان", "مازندران", "کرمان", "البرز"
            ]
        
        # ایجاد کیبورد 2 ستونی
        keyboard = []
        row = []
        
        for i, province in enumerate(provinces):
            row.append(province)
            if len(row) == 2 or i == len(provinces) - 1:
                keyboard.append(row)
                row = []
        
        return ReplyKeyboardMarkup(keyboard, resize_keyboard=True)
    
    def get_province(self, update: Update, context: CallbackContext) -> int:
        """دریافت استان"""
        province = update.message.text.strip()
        user = update.effective_user
        
        # ذخیره استان در سشن
        session = self._get_user_session(user.id)
        session['selected_province'] = province
        
        # رهگیری
        try:
            self.user_stats.track_user(
                user.id, 
                user.username, 
                'select_province',
                province=province
            )
        except Exception as e:
            logger.error(f"خطا در رهگیری انتخاب استان: {e}")
        
        # ایجاد کیبورد شهرها
        keyboard = self._create_cities_keyboard(province, user.id)
        
        update.message.reply_text(
            f"✅ استان {province} انتخاب شد.\n\n"
            "🏘️ لطفاً شهر مورد نظر خود را انتخاب کنید:",
            reply_markup=keyboard
        )
        
        return GET_CITY
    
    def _create_cities_keyboard(self, province, user_id, page=0):
        """ایجاد کیبورد شهرها با صفحه‌بندی"""
        session = self._get_user_session(user_id)
        session['city_page'] = page
        
        cities = self.api_client.get_cities(province)
        
        if not cities or len(cities) == 0:
            cities = ["مرکز استان"]
        
        # محاسبه صفحه‌بندی
        cities_per_page = 15
        total_pages = (len(cities) + cities_per_page - 1) // cities_per_page
        
        # محاسبه محدوده شهرهای صفحه جاری
        start_idx = page * cities_per_page
        end_idx = min(start_idx + cities_per_page, len(cities))
        current_cities = cities[start_idx:end_idx]
        
        # ایجاد کیبورد 3 ستونی
        keyboard = []
        row = []
        
        for i, city in enumerate(current_cities):
            row.append(city)
            if len(row) == 3 or i == len(current_cities) - 1:
                keyboard.append(row)
                row = []
        
        # دکمه‌های ناوبری
        navigation = []
        if page > 0:
            navigation.append("⬅️ شهرهای قبلی")
        if page < total_pages - 1:
            navigation.append("➡️ شهرهای بعدی")
        
        if navigation:
            keyboard.append(navigation)
        
        keyboard.append(["🔙 بازگشت به استان‌ها"])
        
        return ReplyKeyboardMarkup(keyboard, resize_keyboard=True)
    
    def get_city(self, update: Update, context: CallbackContext) -> int:
        """دریافت شهر"""
        text = update.message.text.strip()
        user = update.effective_user
        session = self._get_user_session(user.id)
        
        # بررسی دکمه‌های ناوبری
        if text == "⬅️ شهرهای قبلی":
            province = session.get('selected_province')
            if province:
                current_page = session.get('city_page', 0)
                if current_page > 0:
                    keyboard = self._create_cities_keyboard(
                        province, user.id, current_page - 1
                    )
                    update.message.reply_text(
                        "شهر مورد نظر خود را انتخاب کنید:",
                        reply_markup=keyboard
                    )
            return GET_CITY
        
        elif text == "➡️ شهرهای بعدی":
            province = session.get('selected_province')
            if province:
                current_page = session.get('city_page', 0)
                cities = self.api_client.get_cities(province)
                cities_per_page = 15
                total_pages = (len(cities) + cities_per_page - 1) // cities_per_page
                
                if current_page < total_pages - 1:
                    keyboard = self._create_cities_keyboard(
                        province, user.id, current_page + 1
                    )
                    update.message.reply_text(
                        "شهر مورد نظر خود را انتخاب کنید:",
                        reply_markup=keyboard
                    )
            return GET_CITY
        
        elif text == "🔙 بازگشت به استان‌ها":
            keyboard = self._create_provinces_keyboard()
            update.message.reply_text(
                "لطفاً استان مورد نظر خود را انتخاب کنید:",
                reply_markup=keyboard
            )
            return GET_PROVINCE
        
        # انتخاب شهر
        city = text
        province = session.get('selected_province', 'نامشخص')
        
        session['selected_city'] = city
        session['city_page'] = 0  # ریست صفحه‌بندی
        
        # رهگیری
        try:
            self.user_stats.track_user(
                user.id, 
                user.username, 
                'select_city',
                province=province,
                city=city
            )
        except Exception as e:
            logger.error(f"خطا در رهگیری انتخاب شهر: {e}")
        
        # نمایش منوی جستجو
        return self._show_search_menu(update, context)
    
    def _show_search_menu(self, update: Update, context: CallbackContext):
        """نمایش منوی جستجو"""
        session = self._get_user_session(update.effective_user.id)
        province = session.get('selected_province', 'نامشخص')
        city = session.get('selected_city', 'نامشخص')
        
        keyboard = [
            ["🏠 فروش مسکونی", "🏠 اجاره مسکونی"],
            ["📊 فروش تجاری", "📊 اجاره تجاری"],
            ["🗺️ فروش زمین", "🔙 تغییر شهر"],
            ["📊 مشاهده آمار (ادمین)"]
        ]
        
        update.message.reply_text(
            f"📍 موقعیت: {province} - {city}\n\n"
            "🔍 لطفاً نوع ملک مورد نظر خود را انتخاب کنید:",
            reply_markup=ReplyKeyboardMarkup(keyboard, resize_keyboard=True)
        )
        
        return ADVANCED_SEARCH
    
    def handle_search(self, update: Update, context: CallbackContext):
        """مدیریت جستجو"""
        text = update.message.text.strip()
        user = update.effective_user
        session = self._get_user_session(user.id)
        
        # بررسی دستورات ویژه
        if text == "🔙 تغییر شهر":
            keyboard = self._create_provinces_keyboard()
            update.message.reply_text(
                "لطفاً استان مورد نظر خود را انتخاب کنید:",
                reply_markup=keyboard
            )
            return GET_PROVINCE
        
        elif text == "📊 مشاهده آمار (ادمین)":
            if user.id in ADMIN_IDS:
                return self.show_stats(update, context)
            else:
                update.message.reply_text("❌ شما دسترسی ادمین ندارید.")
                return ADVANCED_SEARCH
        
        # نگاشت نوع ملک
        property_types = {
            "🏠 فروش مسکونی": "فروش خانه / ویلا",
            "🏠 اجاره مسکونی": "اجاره خانه / ویلا",
            "📊 فروش تجاری": "فروش مغازه / واحد تجاری",
            "📊 اجاره تجاری": "اجاره مغازه / واحد تجاری",
            "🗺️ فروش زمین": "فروش زمین"
        }
        
        if text not in property_types:
            update.message.reply_text("❌ لطفاً یکی از گزینه‌های موجود را انتخاب کنید.")
            return ADVANCED_SEARCH
        
        session['selected_type'] = property_types[text]
        session['current_page'] = 0
        
        # رهگیری جستجو
        try:
            self.user_stats.track_user(
                user.id,
                user.username,
                'search',
                province=session.get('selected_province'),
                city=session.get('selected_city')
            )
        except Exception as e:
            logger.error(f"خطا در رهگیری جستجو: {e}")
        
        # نمایش آگهی‌ها
        return self._show_listings_page(update, context)
    
    def _show_listings_page(self, update: Update, context: CallbackContext):
        """نمایش صفحه آگهی‌ها"""
        user = update.effective_user
        session = self._get_user_session(user.id)
        
        province = session.get('selected_province')
        city = session.get('selected_city')
        property_type = session.get('selected_type')
        current_page = session.get('current_page', 0)
        
        if not province or not city:
            update.message.reply_text(
                "لطفاً ابتدا موقعیت مکانی را انتخاب کنید.",
                reply_markup=self._create_provinces_keyboard()
            )
            return GET_PROVINCE
        
        # دریافت آگهی‌ها
        loading_msg = update.message.reply_text("🔍 در حال دریافت آگهی‌ها...")
        
        listings = self.api_client.get_listings(province, city, property_type)
        
        # حذف پیام در حال بارگذاری
        try:
            context.bot.delete_message(
                chat_id=update.effective_chat.id,
                message_id=loading_msg.message_id
            )
        except:
            pass
        
        if not listings:
            keyboard = [
                ["🔍 جستجوی جدید", "🔙 تغییر شهر"]
            ]
            
            update.message.reply_text(
                f"📭 در حال حاضر آگهی‌ای در {province} - {city} یافت نشد.\n\n"
                f"دسته‌بندی: {property_type}\n"
                "لطفاً نوع ملک یا موقعیت مکانی را تغییر دهید.",
                reply_markup=ReplyKeyboardMarkup(keyboard, resize_keyboard=True)
            )
            return VIEW_LISTINGS
        
        # ذخیره لیست آگهی‌ها
        session['listings'] = listings
        total_listings = len(listings)
        
        # محاسبه صفحات
        per_page = 5
        total_pages = (total_listings + per_page - 1) // per_page
        current_page = max(0, min(current_page, total_pages - 1))
        session['current_page'] = current_page
        
        # نمایش خلاصه
        summary = (
            f"🏠 آگهی‌های {property_type}\n"
            f"📍 موقعیت: {province} - {city}\n"
            f"📊 تعداد کل: {total_listings} آگهی\n"
            f"📄 صفحه: {current_page + 1} از {total_pages}\n"
        )
        
        update.message.reply_text(summary)
        
        # نمایش آگهی‌های صفحه جاری
        start_idx = current_page * per_page
        end_idx = min(start_idx + per_page, total_listings)
        
        for i in range(start_idx, end_idx):
            listing = listings[i]
            message = self._format_listing(listing)
            
            try:
                update.message.reply_text(
                    message,
                    parse_mode='HTML',
                    disable_web_page_preview=True
                )
            except Exception as e:
                logger.error(f"خطا در ارسال آگهی: {e}")
                continue
        
        # نمایش دکمه‌های ناوبری
        keyboard = []
        
        if total_pages > 1:
            nav_row = []
            if current_page > 0:
                nav_row.append("⬅️ صفحه قبلی")
            if current_page < total_pages - 1:
                nav_row.append("➡️ صفحه بعدی")
            if nav_row:
                keyboard.append(nav_row)
        
        keyboard.append(["🔍 جستجوی جدید", "🔙 تغییر شهر"])
        
        update.message.reply_text(
            "از دکمه‌های زیر برای پیمایش استفاده کنید:",
            reply_markup=ReplyKeyboardMarkup(keyboard, resize_keyboard=True)
        )
        
        return VIEW_LISTINGS
    
    def _format_listing(self, listing):
        """قالب‌بندی آگهی"""
        try:
            title = listing.get('titleAd', 'بدون عنوان')
            price = listing.get('price', 'قیمت تماس')
            
            # ترکیب قیمت برای اجاره‌ای‌ها
            if price == 'قیمت تماس':
                deposite = listing.get('deposite')
                rent = listing.get('rent')
                if deposite or rent:
                    parts = []
                    if deposite:
                        parts.append(f"ودیعه: {deposite}")
                    if rent:
                        parts.append(f"اجاره: {rent}")
                    price = " + ".join(parts)
            
            location = f"{listing.get('province', '')} - {listing.get('city', '')}"
            description = listing.get('discription', 'بدون توضیحات')
            property_type = listing.get('type', 'نامشخص')
            area = listing.get('area', 'نامشخص')
            bedrooms = listing.get('bedroom')
            
            # پاکسازی توضیحات
            import re
            description = re.sub(r'<[^>]+>', '', description)
            if len(description) > 300:
                description = description[:300] + "..."
            
            # ساخت لینک
            listing_id = listing.get('id', '')
            url_mapping = {
                "خانه فروشی": "Realestate/Homesellings/detail",
                "خانه اجاره ایی": "Realestate/Homerent/detail",
                "فروش زمین": "Realestate/Landselling/detail",
                "فروش مغازه": "Realestate/Storeselling/detail",
                "اجاره مغازه": "Realestate/Storerent/detail"
            }
            
            base_path = url_mapping.get(property_type, "listing")
            details_url = f"https://amlakjame.ir/{base_path}{listing_id}" if listing_id else "https://amlakjame.ir"
            
            # ساخت پیام
            message_parts = [
                f"🏠 <b>{self._escape_html(title)}</b>",
                "",
                f"💰 <b>قیمت:</b> {self._escape_html(str(price))}",
                f"📍 <b>موقعیت:</b> {self._escape_html(location)}",
                f"📐 <b>نوع:</b> {self._escape_html(property_type)}",
                f"📏 <b>متراژ:</b> {self._escape_html(str(area))}",
            ]
            
            if bedrooms is not None:
                message_parts.append(f"🛏️ <b>تعداد خواب:</b> {bedrooms}")
            
            message_parts.extend([
                "",
                f"📝 <b>توضیحات:</b>",
                self._escape_html(description),
                "",
                f'🔗 <a href="{details_url}">مشاهده جزئیات و تماس</a>'
            ])
            
            return "\n".join(message_parts)
            
        except Exception as e:
            logger.error(f"خطا در قالب‌بندی آگهی: {e}")
            return "❌ خطا در نمایش اطلاعات آگهی"
    
    def _escape_html(self, text):
        """فرار کردن کاراکترهای HTML"""
        if text is None:
            return ""
        
        text = str(text)
        escape_map = {
            '&': '&amp;',
            '<': '&lt;',
            '>': '&gt;',
            '"': '&quot;',
            "'": '&#39;'
        }
        
        for char, escaped in escape_map.items():
            text = text.replace(char, escaped)
        
        return text
    
    def handle_navigation(self, update: Update, context: CallbackContext):
        """مدیریت ناوبری صفحات"""
        text = update.message.text.strip()
        user = update.effective_user
        session = self._get_user_session(user.id)
        
        if text == "⬅️ صفحه قبلی":
            current_page = session.get('current_page', 0)
            if current_page > 0:
                session['current_page'] = current_page - 1
                return self._show_listings_page(update, context)
            else:
                update.message.reply_text("شما در اولین صفحه هستید.")
                
        elif text == "➡️ صفحه بعدی":
            current_page = session.get('current_page', 0)
            listings = session.get('listings', [])
            per_page = 5
            total_pages = (len(listings) + per_page - 1) // per_page
            
            if current_page < total_pages - 1:
                session['current_page'] = current_page + 1
                return self._show_listings_page(update, context)
            else:
                update.message.reply_text("شما در آخرین صفحه هستید.")
                
        elif text == "🔍 جستجوی جدید":
            return self._show_search_menu(update, context)
            
        elif text == "🔙 تغییر شهر":
            keyboard = self._create_provinces_keyboard()
            update.message.reply_text(
                "لطفاً استان مورد نظر خود را انتخاب کنید:",
                reply_markup=keyboard
            )
            return GET_PROVINCE
        
        return VIEW_LISTINGS
    
    def show_stats(self, update: Update, context: CallbackContext):
        """نمایش آمار (برای ادمین)"""
        user = update.effective_user
        
        if user.id not in ADMIN_IDS:
            update.message.reply_text("❌ دسترسی غیرمجاز")
            return ADVANCED_SEARCH
        
        try:
            stats = self.user_stats.get_stats_summary()
            
            # ساخت لیست استان‌ها و شهرها
            provinces_list = "\n".join([
                f"• {prov}: {count}" for prov, count in stats['top_provinces']
            ]) or "هیچ داده‌ای"
            
            cities_list = "\n".join([
                f"• {city}: {count}" for city, count in stats['top_cities']
            ]) or "هیچ داده‌ای"
            
            message = f"""
📊 <b>آمار ربات املاک جامع</b>

👥 <b>آمار کاربران:</b>
├ کل کاربران: {stats['total_users']}
├ کاربران جدید امروز: {stats['today_new_users']}
└ کاربران فعال این هفته: {stats['weekly_active_users']}

📈 <b>آمار امروز:</b>
├ اقدامات: {stats['today_actions']}
├ جستجوها: {stats['today_searches']}
└ کل جستجوها: {stats['total_searches']}

📅 <b>آمار هفته جاری:</b>
├ کاربران جدید: {stats['weekly_new_users']}
├ اقدامات: {stats['weekly_actions']}
└ جستجوها: {stats['weekly_searches']}

🏙️ <b>محبوب‌ترین استان‌ها:</b>
{provinces_list}

🏘️ <b>محبوب‌ترین شهرها:</b>
{cities_list}

🕒 <b>آخرین به‌روزرسانی:</b>
{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}
            """
            
            update.message.reply_text(message, parse_mode='HTML')
            
        except Exception as e:
            logger.error(f"خطا در نمایش آمار: {e}")
            update.message.reply_text("❌ خطا در دریافت آمار. لطفاً بعداً تلاش کنید.")
        
        keyboard = [
            ["🔍 جستجوی جدید", "🔙 تغییر شهر"]
        ]
        update.message.reply_text(
            "منو:",
            reply_markup=ReplyKeyboardMarkup(keyboard, resize_keyboard=True)
        )
        
        return ADVANCED_SEARCH
    
    def cancel(self, update: Update, context: CallbackContext):
        """لغو عملیات"""
        user = update.effective_user
        self._clear_user_session(user.id)
        
        update.message.reply_text(
            "عملیات لغو شد.\nبرای شروع مجدد /start را ارسال کنید.",
            reply_markup=ReplyKeyboardRemove()
        )
        
        return ConversationHandler.END
    
    def error_handler(self, update: Update, context: CallbackContext):
        """مدیریت خطاها"""
        error = context.error
        
        logger.error(f"خطا در پردازش بروزرسانی: {error}", exc_info=True)
        
        try:
            if update and update.effective_message:
                update.effective_message.reply_text(
                    "⚠️ خطایی رخ داد. لطفاً دوباره تلاش کنید."
                )
        except:
            pass
        
        # پاک کردن سشن کاربر در صورت خطای بحرانی
        if update and update.effective_user:
            user_id = update.effective_user.id
            if user_id in self.user_sessions:
                del self.user_sessions[user_id]

def check_running_instances():
    """بررسی نمونه‌های در حال اجرا"""
    import subprocess
    
    try:
        result = subprocess.run(
            ['ps', 'aux'],
            capture_output=True,
            text=True
        )
        
        current_pid = str(os.getpid())
        bot_processes = []
        
        for line in result.stdout.split('\n'):
            if 'python' in line and 'bot' in line.lower():
                if current_pid not in line:
                    bot_processes.append(line.strip())
        
        return bot_processes
    except:
        return []

def cleanup():
    """تمیزکاری هنگام خروج"""
    print("\n🔄 در حال خروج از ربات...")
    
    # پاک کردن فایل PID
    pid_file = 'bot.pid'
    if os.path.exists(pid_file):
        os.remove(pid_file)
    
    print("✅ خروج موفق")

def main():
    """تابع اصلی"""
    # بررسی توکن
    if not BOT_TOKEN:
        print("❌ BOT_TOKEN یافت نشد. لطفاً در فایل .env تنظیم کنید.")
        sys.exit(1)
    
    # بررسی نمونه‌های در حال اجرا
    running_instances = check_running_instances()
    if running_instances:
        print("⚠️ نمونه‌های قبلی ربات پیدا شد:")
        for proc in running_instances[:3]:  # فقط ۳ مورد اول
            print(f"  - {proc[:80]}...")
        print("لطفاً نمونه‌های قبلی را متوقف کنید:")
        print("  pkill -f python")
    
    # ثبت توابع تمیزکاری
    atexit.register(cleanup)
    signal.signal(signal.SIGINT, lambda sig, frame: sys.exit(0))
    signal.signal(signal.SIGTERM, lambda sig, frame: sys.exit(0))
    
    try:
        # ایجاد ربات
        bot = AmlakJameBot()
        
        # ایجاد Updater بدون request_kwargs مشکوک
        updater = Updater(BOT_TOKEN, use_context=True)
        
        dp = updater.dispatcher
        
        # اضافه کردن خطایاب
        dp.add_error_handler(bot.error_handler)
        
        # اضافه کردن دستورات
        dp.add_handler(CommandHandler("stats", bot.show_stats))
        
        # مکالمه اصلی
        conv_handler = ConversationHandler(
            entry_points=[CommandHandler('start', bot.start)],
            states={
                GET_PROVINCE: [
                    MessageHandler(Filters.text & ~Filters.command, bot.get_province)
                ],
                GET_CITY: [
                    MessageHandler(Filters.text & ~Filters.command, bot.get_city)
                ],
                ADVANCED_SEARCH: [
                    MessageHandler(Filters.text & ~Filters.command, bot.handle_search)
                ],
                VIEW_LISTINGS: [
                    MessageHandler(Filters.text & ~Filters.command, bot.handle_navigation)
                ],
            },
            fallbacks=[
                CommandHandler('cancel', bot.cancel),
                CommandHandler('start', bot.start)
            ],
            allow_reentry=True
        )
        
        dp.add_handler(conv_handler)
        
        # ذخیره PID
        with open('bot.pid', 'w') as f:
            f.write(str(os.getpid()))
        
        # شروع ربات
        print("=" * 50)
        print("🤖 ربات املاک جامع")
        print("=" * 50)
        print(f"🕒 زمان شروع: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
        print(f"🐍 پایتون: {sys.version.split()[0]}")
        print(f"🔗 API: {API_BASE_URL}")
        
        bot_info = updater.bot.get_me()
        print(f"🤖 ربات: @{bot_info.username}")
        print("=" * 50)
        print("📡 در حال گوش دادن به پیام‌ها...")
        print("برای توقف: Ctrl+C")
        
        # شروع polling با تنظیمات ساده
        updater.start_polling(
            poll_interval=1.0,
            timeout=15,
            drop_pending_updates=True
        )
        
        updater.idle()
        
    except Exception as e:
        logger.error(f"خطا در اجرای ربات: {e}", exc_info=True)
        print(f"❌ خطا: {e}")
        sys.exit(1)

if __name__ == '__main__':
    main()