"""
DataVault Client — Basic Tier
==============================
Consumer-side client for browsing and purchasing DataVault reports.

This is included in the Basic package. Allows nodes to:
    - Browse the report catalog
    - Search by keyword
    - Purchase access to reports
    - Download purchased PDFs

Report generation is NOT available in Basic — requires Pro tier.
"""

import os
import json
import logging
import requests
from typing import Dict, List, Optional, Any

logger = logging.getLogger("biznode.datavault.client")

# DataVault API base URL — points to the dashboard server
_DASHBOARD_URL = os.getenv("DASHBOARD_URL", "http://localhost:7777")
_API_BASE = f"{_DASHBOARD_URL}/api/datavault"


def _headers() -> Dict[str, str]:
    """Standard request headers."""
    secret = os.getenv("BOT_SECRET", "")
    return {"X-Bot-Secret": secret, "Content-Type": "application/json"}


# ---------------------------------------------------------------------------
# Browse & Search
# ---------------------------------------------------------------------------

def get_vault_stats() -> Dict[str, Any]:
    """Get DataVault statistics."""
    try:
        r = requests.get(f"{_API_BASE}/stats", headers=_headers(), timeout=10)
        r.raise_for_status()
        return r.json()
    except Exception as e:
        logger.error(f"Failed to get vault stats: {e}")
        return {}


def list_plugins() -> List[Dict[str, Any]]:
    """List available plugins."""
    try:
        r = requests.get(f"{_API_BASE}/plugins", headers=_headers(), timeout=10)
        r.raise_for_status()
        return r.json().get("plugins", [])
    except Exception as e:
        logger.error(f"Failed to list plugins: {e}")
        return []


def list_commands() -> List[Dict[str, Any]]:
    """List available report commands."""
    try:
        r = requests.get(f"{_API_BASE}/commands", headers=_headers(), timeout=10)
        r.raise_for_status()
        return r.json().get("commands", [])
    except Exception as e:
        logger.error(f"Failed to list commands: {e}")
        return []


def browse_reports(
    plugin_id: str = "",
    category: str = "",
    limit: int = 50,
    offset: int = 0,
) -> List[Dict[str, Any]]:
    """Browse available reports."""
    try:
        params = {"limit": limit, "offset": offset}
        if plugin_id:
            params["plugin_id"] = plugin_id
        if category:
            params["category"] = category
        r = requests.get(f"{_API_BASE}/reports", params=params, headers=_headers(), timeout=10)
        r.raise_for_status()
        return r.json().get("reports", [])
    except Exception as e:
        logger.error(f"Failed to browse reports: {e}")
        return []


def search_reports(query: str, limit: int = 20) -> List[Dict[str, Any]]:
    """Search reports by keyword."""
    try:
        r = requests.get(
            f"{_API_BASE}/reports/search",
            params={"q": query, "limit": limit},
            headers=_headers(),
            timeout=10,
        )
        r.raise_for_status()
        return r.json().get("results", [])
    except Exception as e:
        logger.error(f"Failed to search reports: {e}")
        return []


def get_report(report_id: str) -> Optional[Dict[str, Any]]:
    """Get details of a specific report."""
    try:
        r = requests.get(f"{_API_BASE}/reports/{report_id}", headers=_headers(), timeout=10)
        r.raise_for_status()
        return r.json()
    except Exception as e:
        logger.error(f"Failed to get report: {e}")
        return None


# ---------------------------------------------------------------------------
# Purchase & Download
# ---------------------------------------------------------------------------

def purchase_report(
    report_id: str,
    buyer_node: str = "",
    buyer_telegram: str = "",
    buyer_email: str = "",
    payment_method: str = "BZeUSD",
) -> Optional[Dict[str, Any]]:
    """
    Initiate purchase of a report.
    Free reports are auto-confirmed.
    Paid reports return purchase details for payment processing.
    """
    try:
        payload = {
            "buyer_node": buyer_node,
            "buyer_telegram": buyer_telegram,
            "buyer_email": buyer_email,
            "payment_method": payment_method,
        }
        r = requests.post(
            f"{_API_BASE}/reports/{report_id}/purchase",
            json=payload,
            headers=_headers(),
            timeout=15,
        )
        r.raise_for_status()
        return r.json()
    except Exception as e:
        logger.error(f"Failed to purchase report: {e}")
        return None


def download_report(
    report_id: str,
    output_path: str,
    buyer_telegram: str = "",
    buyer_node: str = "",
) -> bool:
    """
    Download a purchased report PDF.
    Returns True if download was successful.
    """
    try:
        params = {}
        if buyer_telegram:
            params["buyer_telegram"] = buyer_telegram
        if buyer_node:
            params["buyer_node"] = buyer_node

        r = requests.get(
            f"{_API_BASE}/reports/{report_id}/download",
            params=params,
            headers=_headers(),
            timeout=30,
        )
        r.raise_for_status()

        os.makedirs(os.path.dirname(output_path), exist_ok=True)
        with open(output_path, "wb") as f:
            f.write(r.content)
        logger.info(f"Report downloaded: {output_path}")
        return True
    except Exception as e:
        logger.error(f"Failed to download report: {e}")
        return False


def list_purchases(
    buyer_telegram: str = "",
    status: str = "",
    limit: int = 50,
) -> List[Dict[str, Any]]:
    """List your purchases."""
    try:
        params = {"limit": limit}
        if buyer_telegram:
            params["buyer_telegram"] = buyer_telegram
        if status:
            params["status"] = status
        r = requests.get(f"{_API_BASE}/purchases", params=params, headers=_headers(), timeout=10)
        r.raise_for_status()
        return r.json().get("purchases", [])
    except Exception as e:
        logger.error(f"Failed to list purchases: {e}")
        return []
