import logging
import requests
from datetime import datetime
import random
import threading
import time
import urllib.parse

_vnii_check_attempted = False

class AdCategory:
    FREE = 0
    MANDATORY = 1
    ANNOUNCEMENT = 2
    REFERRAL = 3
    FEATURE = 4
    GUIDE = 5
    SURVEY = 6
    PROMOTION = 7
    SECURITY = 8
    MAINTENANCE = 9
    WARNING = 10

# Thêm import kiểm tra license từ vnii
try:
    from vnii import lc_init
except ImportError:
    lc_init = None  # Nếu không có vnii, không xác định được trạng thái license

# Module-level logger setup
logger = logging.getLogger(__name__)
if not logger.hasHandlers():
    # Add a simple stream handler that only outputs the message text
    handler = logging.StreamHandler()
    handler.setFormatter(logging.Formatter('%(message)s'))
    logger.addHandler(handler)
    # Set to ERROR level to minimize output
    logger.setLevel(logging.ERROR)

class ContentManager:
    """
    Singleton manager to fetch remote or fallback promotional content and
    present it in different environments (Jupyter, terminal, other).

    Displays content automatically at randomized intervals via a background thread.
    """
    _instance = None
    _lock = threading.Lock()

    def __new__(cls):
        """
        Ensure only one instance of ContentManager is created (thread-safe).
        """
        with cls._lock:
            if cls._instance is None:
                cls._instance = super(ContentManager, cls).__new__(cls)
                cls._instance._initialize()
            return cls._instance

    def _initialize(self, debug=False):
        """
        Internal initializer: sets up display timing, URLs, and starts the periodic display thread.
        """
        # Set up content base URL
        self.content_base_url = "https://hq.vnstocks.com/content-delivery"
        self.is_paid_user = None  # Mặc định: chưa xác định
        self.license_checked = False
        self._debug = debug
        global _vnii_check_attempted
        if _vnii_check_attempted:
            # Đã kiểm tra/cài đặt vnii trước đó, không làm lại nữa
            return
        _vnii_check_attempted = True
        # Nếu máy đã từng cài vnii, luôn cài lại bản mới nhất; nếu chưa từng cài thì không xác định được trạng thái license
        import sys
        import importlib
        try:
            import importlib.metadata
            VNII_LATEST_VERSION = "0.1.1"
            VNII_URL = f"https://github.com/vnstock-hq/licensing/releases/download/vnii-{VNII_LATEST_VERSION}/vnii-{VNII_LATEST_VERSION}.tar.gz"
            import subprocess
            try:
                old_version = importlib.metadata.version("vnii")
                # Chỉ cài nếu version chưa đúng
                if old_version != VNII_LATEST_VERSION:
                    try:
                        subprocess.check_call([
                            sys.executable, "-m", "pip", "install", f"vnii@{VNII_URL}", "--quiet"
                        ], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
                        importlib.invalidate_caches()
                        if "vnii" in sys.modules:
                            importlib.reload(sys.modules["vnii"])
                        else:
                            import vnii
                        new_version = importlib.metadata.version("vnii")
                    except Exception as e:
                        logger.error(f"Lỗi khi cài đặt vnii: {e}")
                        pass
                # Nếu đã đúng version thì không log gì cả
            except importlib.metadata.PackageNotFoundError:
                # Nếu chưa từng cài, không cài, luôn coi là free user
                self.is_paid_user = False
                return
        except Exception as e:
            logger.error(f"Lỗi khi kiểm tra/cài đặt vnii: {e}")
            user_msg = (
                "Không thể tự động cài đặt/cập nhật vnii. "
                "Vui lòng liên hệ admin hoặc hỗ trợ kỹ thuật của Vnstock để được trợ giúp. "
                f"Chi tiết lỗi: {e}"
            )
            logger.error(user_msg)
            try:
                print(user_msg)
            except Exception:
                pass
            self.is_paid_user = False
            return

        # Kiểm tra trạng thái paid user (sponsor) và cache lại
        if lc_init is not None:
            try:
                license_info = lc_init(repo_name='vnstock', debug=self._debug)
                status = license_info.get('status', '').lower()
                if self._debug:
                    logger.info(f"License check result: {status}")
                if 'recognized and verified' in status:
                    self.is_paid_user = True
                    if self._debug:
                        logger.info("Detected paid user (license recognized and verified).")
                else:
                    self.is_paid_user = False
                    if self._debug:
                        logger.info("Detected free user (license not recognized/verified).")
                self.license_checked = True
            except Exception as e:
                if self._debug:
                    logger.error(f"Lỗi khi kiểm tra license với lc_init: {e}")
                self.is_paid_user = None
        else:
            if self._debug:
                logger.warning("Không tìm thấy package vnii. Không xác định được trạng thái paid user.")
            self.is_paid_user = None

        # Timestamp of last content display (epoch seconds)
        self.last_display = 0
        # Minimum interval between displays (24 hours)
        self.display_interval = 24 * 3600

        # Base endpoints for fetching remote content and linking
        self.content_base_url = "https://hq.vnstocks.com/content-delivery"
        self.target_url = "https://vnstocks.com/lp-khoa-hoc-python-chung-khoan"
        self.image_url = (
            "https://vnstocks.com/img/trang-chu-vnstock-python-api-phan-tich-giao-dich-chung-khoan.jpg"
        )

        # Launch the background thread to periodically present content
        self._start_periodic_display()

    def _start_periodic_display(self):
        """
        Launch a daemon thread that sleeps a random duration between 2–6 hours,
        then checks if the display interval has elapsed and calls present_content.
        """
        def periodic_display():
            while True:
                # Nếu là paid user thì không bao giờ hiện ads
                if self.is_paid_user:
                    break
                # Randomize sleep to avoid synchronized requests across instances
                sleep_time = random.randint(2 * 3600, 6 * 3600)
                time.sleep(sleep_time)

                # Present content if enough time has passed since last_display
                current_time = time.time()
                if current_time - self.last_display >= self.display_interval:
                    self.present_content(context="periodic")
                else:
                    pass

        thread = threading.Thread(target=periodic_display, daemon=True)
        thread.start()

    def fetch_remote_content(self, context: str = "init", html: bool = True) -> str:
        if self.is_paid_user:
            return ""

        """
        Fetch promotional content from remote service with context and format flag.

        Args:
            context: usage context (e.g., "init", "periodic", "loop").
            html: if True, request HTML; otherwise plain text.

        Returns:
            The content string on HTTP 200, or None on failure.
        """
        try:
            # Build query params and URL
            params = {"context": context, "html": "true" if html else "false"}
            url = f"{self.content_base_url}?{urllib.parse.urlencode(params)}"

            response = requests.get(url, timeout=3)
            if response.status_code == 200:
                return response.text
            # Log non-200 responses at debug level
            logger.error(f"Non-200 response fetching content: {response.status_code}")
            return None
        except Exception as e:
            # Log exceptions without interrupting user code
            logger.error(f"Failed to fetch remote content: {e}")
            return None

    def present_content(self, context: str = "init", ad_category: int = AdCategory.FREE) -> None:
        environment = None
        """
        Display promotional content in the appropriate environment.
        ad_category: Loại quảng cáo (FREE, ANNOUNCEMENT, ...)
        """
        # Nếu là paid user và ad_category là FREE thì skip, còn lại vẫn hiện
        if getattr(self, 'is_paid_user', False) and ad_category == AdCategory.FREE:
            return

        # Update last display timestamp
        self.last_display = time.time()

        # Auto-detect environment if not provided
        if environment is None:
            try:
                from vnai.scope.profile import inspector
                environment = inspector.examine().get("environment", "unknown")
            except Exception as e:
                logger.error(f"Không detect được environment: {e}")
                environment = "unknown"

        # Retrieve remote or HTML/text content based on environment
        remote_content = self.fetch_remote_content(
            context=context, html=(environment == "jupyter")
        )

        # Generate fallback messages if remote fetch fails
        fallback = self._generate_fallback_content(context)

        if environment == "jupyter":
            try:
                from IPython.display import display, HTML, Markdown

                if remote_content:
                    display(HTML(remote_content))
                else:
                    try:
                        display(Markdown(fallback["markdown"]))
                    except Exception as e:
                        display(HTML(fallback["html"]))
            except Exception as e:
                pass

        elif environment == "terminal":
            # Hiển thị quảng cáo dạng text ra terminal
            if remote_content:
                print(remote_content)
            else:
                print(fallback["terminal"])

        else:
            print(fallback["simple"])

    def _generate_fallback_content(self, context):
        fallback = {"html": "", "markdown": "", "terminal": "", "simple": ""}

        if context == "loop":
            fallback["html"] = (
                f"""
            <div style="border: 1px solid #e74c3c; padding: 15px; border-radius: 5px; margin: 10px 0;">
                <h3 style="color: #e74c3c;">⚠️ Bạn đang sử dụng vòng lặp với quá nhiều requests</h3>
                <p>Để tránh bị giới hạn tốc độ và tối ưu hiệu suất:</p>
                <ul>
                    <li>Thêm thời gian chờ giữa các lần gọi API</li>
                    <li>Sử dụng xử lý theo batch thay vì lặp liên tục</li>
                    <li>Tham gia gói tài trợ <a href="https://vnstocks.com/insiders-program" style="color: #3498db;">Vnstock Insider</a> để tăng 5X giới hạn API</li>
                </ul>
            </div>
            """
            )
            fallback["markdown"] = (
                """
## ⚠️ Bạn đang sử dụng vòng lặp với quá nhiều requests

Để tránh bị giới hạn tốc độ và tối ưu hiệu suất:
* Thêm thời gian chờ giữa các lần gọi API
* Sử dụng xử lý theo batch thay vì lặp liên tục
* Tham gia gói tài trợ [Vnstock Insider](https://vnstocks.com/insiders-program) để tăng 5X giới hạn API
            """
            )
            fallback["terminal"] = (
                """
╔═════════════════════════════════════════════════════════════════╗
║                                                                 ║
║   🚫 ĐANG BỊ CHẶN BỞI GIỚI HẠN API? GIẢI PHÁP Ở ĐÂY!            ║
║                                                                 ║
║   ✓ Tăng ngay 500% tốc độ gọi API - Không còn lỗi RateLimit     ║
║   ✓ Tiết kiệm 85% thời gian chờ đợi giữa các request            ║
║                                                                 ║
║   ➤ NÂNG CẤP NGAY VỚI GÓI TÀI TRỢ VNSTOCK:                      ║
║     https://vnstocks.com/insiders-program                       ║
║                                                                 ║
╚═════════════════════════════════════════════════════════════════╝
                """
            )
            fallback["simple"] = (
                "🚫 Đang bị giới hạn API? Tăng tốc độ gọi API lên 500% với gói "
                "Vnstock Insider: https://vnstocks.com/insiders-program"
            )
        else:
            fallback["html"] = (
                f"""
            <div style="border: 1px solid #3498db; padding: 15px; border-radius: 5px; margin: 10px 0;">
                <h3 style="color: #3498db;">👋 Chào mừng bạn đến với Vnstock!</h3>
                <p>Cảm ơn bạn đã sử dụng thư viện phân tích chứng khoán #1 tại Việt Nam cho Python</p>
                <ul>
                    <li>Tài liệu: <a href="https://vnstocks.com/docs/category/s%E1%BB%95-tay-h%C6%B0%E1%BB%9Bng-d%E1%BA%ABn" style="color: #3498db;">vnstocks.com/docs</a></li>
                    <li>Cộng đồng: <a href="https://www.facebook.com/groups/vnstock.official" style="color: #3498db;">vnstocks.com/community</a></li>
                </ul>
                <p>Khám phá các tính năng mới nhất và tham gia cộng đồng để nhận hỗ trợ.</p>
            </div>
            """
            )
            fallback["markdown"] = (
                """
## 👋 Chào mừng bạn đến với Vnstock!

Cảm ơn bạn đã sử dụng package phân tích chứng khoán #1 tại Việt Nam

* Tài liệu: [Sổ tay hướng dẫn](https://vnstocks.com/docs)
* Cộng đồng: [Nhóm Facebook](https://facebook.com/groups/vnstock.official)

Khám phá các tính năng mới nhất và tham gia cộng đồng để nhận hỗ trợ.
                """
            )
            fallback["terminal"] = (
                """
╔════════════════════════════════════════════════════════════╗
║                                                            ║
║  👋 Chào mừng bạn đến với Vnstock!                         ║
║                                                            ║
║  Cảm ơn bạn đã sử dụng package phân tích                   ║
║  chứng khoán #1 tại Việt Nam                               ║
║                                                            ║
║  ✓ Tài liệu: https://vnstocks.com/docs                     ║
║  ✓ Cộng đồng: https://facebook.com/groups/vnstock.official ║
║                                                            ║
║  Khám phá các tính năng mới nhất và tham gia               ║
║  cộng đồng để nhận hỗ trợ.                                 ║
║                                                            ║
╚════════════════════════════════════════════════════════════╝
                """
            )
            fallback["simple"] = (
                "👋 Chào mừng bạn đến với Vnstock! "
                "Tài liệu: https://vnstocks.com/onboard | "
                "Cộng đồng: https://facebook.com/groups/vnstock.official"
            )
        return fallback

# Singleton instance for module-level use
manager = ContentManager()

def present(context: str = "init", ad_category: int = AdCategory.FREE) -> None:
    """
    Shortcut to ContentManager.present_content for external callers.

    Args:
        context: propagate context string to ContentManager.
        ad_category: loại quảng cáo (FREE, ANNOUNCEMENT, ...)
    """
    manager.present_content(context=context, ad_category=ad_category)
