"""
SociaVault API Client - TikTok Shop Data

Endpoints:
- Search products by keyword
- Get store products (all products from a shop)
- Get product details (stock, price, SKUs, reviews, related videos)
- Get product reviews

Docs: https://docs.sociavault.com/api-reference/introduction
Base URL: https://api.sociavault.com
Auth: X-API-Key header
Cost: 1 credit per request
"""

import logging
from datetime import datetime

import requests

logger = logging.getLogger(__name__)

BASE_URL = "https://api.sociavault.com"
TIMEOUT = 30


class SociaVaultClient:
    def __init__(self, api_key: str):
        self.api_key = api_key
        self.headers = {
            "X-API-Key": api_key,
            "Accept": "application/json",
        }

    def _get(self, path: str, params: dict = None) -> dict:
        """Make GET request to SociaVault API."""
        url = f"{BASE_URL}{path}"
        try:
            r = requests.get(url, headers=self.headers, params=params, timeout=TIMEOUT)
            r.raise_for_status()
            data = r.json()
            if not data.get("success"):
                logger.warning(f"SociaVault API returned success=false: {path}")
            return data
        except requests.exceptions.HTTPError as e:
            status = e.response.status_code if e.response else 0
            if status == 401:
                raise ValueError("SociaVault: API key invalida")
            if status == 402:
                raise ValueError("SociaVault: Creditos insuficientes")
            raise
        except Exception as e:
            logger.error(f"SociaVault API error ({path}): {e}")
            raise

    def search_products(self, query: str, page: int = 1, region: str = "BR") -> dict:
        """Search TikTok Shop products by keyword.

        Returns ~30 products per page with sold_count, price, seller info.
        """
        data = self._get("/v1/scrape/tiktok-shop/search", {
            "query": query,
            "page": page,
        })
        inner = data.get("data", data)
        products_raw = inner.get("products", {})

        # Normalize products dict to list
        products = []
        if isinstance(products_raw, dict):
            for key in sorted(products_raw.keys(), key=lambda x: int(x) if x.isdigit() else 0):
                products.append(products_raw[key])
        elif isinstance(products_raw, list):
            products = products_raw

        return {
            "query": inner.get("query", query),
            "total": inner.get("total_products", len(products)),
            "products": [_normalize_product(p) for p in products],
            "credits_used": data.get("credits_used", 1),
        }

    def get_store_products(self, store_url: str, cursor: str = "", region: str = "BR") -> dict:
        """Get all products from a TikTok Shop store.

        Returns shop info + paginated products.
        """
        params = {"url": store_url, "region": region}
        if cursor:
            params["cursor"] = cursor

        data = self._get("/v1/scrape/tiktok-shop/products", params)

        shop_info = data.get("shopInfo", {})
        products_raw = data.get("products", [])
        if isinstance(products_raw, dict):
            products_raw = list(products_raw.values())

        return {
            "shop": _normalize_shop(shop_info),
            "products": [_normalize_product(p) for p in products_raw],
            "credits_used": data.get("credits_used", 1),
        }

    def get_product_details(self, product_url: str, region: str = "BR",
                            get_related_videos: bool = False) -> dict:
        """Get detailed product info: stock, SKUs, reviews, seller, logistics.

        Costs 1 credit. Set get_related_videos=True for promo videos (slower).
        """
        data = self._get("/v1/scrape/tiktok-shop/product-details", {
            "url": product_url,
            "region": region,
            "get_related_videos": "true" if get_related_videos else "false",
        })
        inner = data.get("data", data)
        return _normalize_product_details(inner)

    def get_product_reviews(self, product_url: str = "", product_id: str = "",
                            page: int = 1) -> dict:
        """Get product reviews with ratings, images, verified purchase flag.

        Provide either product_url or product_id.
        """
        params = {"page": page}
        if product_url:
            params["url"] = product_url
        elif product_id:
            params["product_id"] = product_id
        else:
            raise ValueError("Provide product_url or product_id")

        data = self._get("/v1/scrape/tiktok-shop/product-reviews", params)
        inner = data.get("data", data)

        reviews_raw = inner.get("product_reviews", {})
        reviews = []
        if isinstance(reviews_raw, dict):
            for key in sorted(reviews_raw.keys(), key=lambda x: int(x) if x.isdigit() else 0):
                reviews.append(_normalize_review(reviews_raw[key]))
        elif isinstance(reviews_raw, list):
            reviews = [_normalize_review(r) for r in reviews_raw]

        ratings = inner.get("review_ratings", {})
        return {
            "total_reviews": int(ratings.get("review_count", "0").replace(",", "") or 0),
            "overall_score": float(ratings.get("overall_score", 0) or 0),
            "rating_breakdown": ratings.get("rating_result", {}),
            "has_more": inner.get("has_more", False),
            "reviews": reviews,
            "credits_used": data.get("credits_used", 1),
        }


# ─── Normalizers ───────────────────────────────────────────────

def _normalize_product(p: dict) -> dict:
    """Normalize search/store product to a clean dict."""
    price_info = p.get("product_price_info", {})
    sold_info = p.get("sold_info", {})
    seller = p.get("seller_info", {})
    rate = p.get("rate_info", {})
    image = p.get("image", {})
    seo = p.get("seo_url", {})

    sold_count = int(sold_info.get("sold_count", 0) or 0)

    return {
        "product_id": p.get("product_id", ""),
        "title": p.get("title", ""),
        "image": _get_image_url(image),
        "url": seo.get("canonical_url", ""),
        "price": price_info.get("sale_price_format", price_info.get("sale_price_decimal", "")),
        "original_price": price_info.get("origin_price_format", ""),
        "discount": price_info.get("discount_format", ""),
        "currency": price_info.get("currency_symbol", "$"),
        "sold_count": sold_count,
        "sold_formatted": _format_number(sold_count),
        "rating": float(rate.get("score", 0) or 0),
        "review_count": int(str(rate.get("review_count", "0")).replace(",", "") or 0),
        "seller_id": seller.get("seller_id", ""),
        "shop_name": seller.get("shop_name", ""),
    }


def _normalize_shop(s: dict) -> dict:
    """Normalize shop info."""
    return {
        "seller_id": s.get("seller_id", ""),
        "shop_name": s.get("shop_name", ""),
        "shop_logo": _get_image_url(s.get("shop_logo", {})),
        "shop_rating": s.get("shop_rating", ""),
        "shop_link": s.get("shop_link", ""),
        "region": s.get("region", ""),
        "sold_count": int(s.get("sold_count", 0) or 0),
        "sold_formatted": s.get("format_sold_count", ""),
        "product_count": int(s.get("on_sell_product_count", 0) or 0),
        "product_count_formatted": s.get("display_on_sell_product_count", ""),
        "followers": s.get("format_followers_count", ""),
        "description": s.get("desc", ""),
        "creator_name": s.get("creator_name", ""),
        "sub_scores": [
            {"type": sc.get("type"), "score": sc.get("score"), "pct": sc.get("score_percentage")}
            for sc in s.get("store_sub_score", [])
        ],
    }


def _normalize_product_details(d: dict) -> dict:
    """Normalize product details response."""
    base = d.get("product_base", {})
    seller = d.get("seller", {})
    price = base.get("price", {})
    review = d.get("product_detail_review", {})
    logistic = d.get("logistic", {})
    skus = d.get("skus", [])

    images = []
    for img in base.get("images", []):
        url = _get_image_url(img)
        if url:
            images.append(url)

    total_stock = sum(int(sku.get("stock", 0) or 0) for sku in skus)

    return {
        "product_id": d.get("product_id", ""),
        "status": d.get("status", 0),
        "title": base.get("title", ""),
        "images": images,
        "image": images[0] if images else "",
        "category": base.get("category_name", ""),
        "sold_count": int(base.get("sold_count", 0) or 0),
        "price": price.get("real_price", ""),
        "original_price": price.get("original_price", ""),
        "discount": price.get("discount", ""),
        "currency": price.get("currency_symbol", price.get("currency", "$")),
        "seller": {
            "seller_id": seller.get("seller_id", ""),
            "name": seller.get("name", ""),
            "product_count": seller.get("product_count", 0),
            "rating": seller.get("rating", ""),
            "location": seller.get("seller_location", ""),
        },
        "stock": total_stock,
        "skus": [
            {
                "sku_id": sku.get("sku_id", ""),
                "stock": int(sku.get("stock", 0) or 0),
                "price": sku.get("price", {}).get("real_price", ""),
            }
            for sku in skus
        ],
        "logistics": {
            "delivery": logistic.get("delivery_name", ""),
            "lead_time": logistic.get("lead_time", ""),
            "free_shipping": logistic.get("free_shipping", False),
        },
        "rating": float(review.get("product_rating", 0) or 0),
        "review_count": int(review.get("review_count", 0) or 0),
        "specifications": base.get("specifications", []),
    }


def _normalize_review(r: dict) -> dict:
    """Normalize a single review."""
    images = r.get("review_images", {})
    image_list = []
    if isinstance(images, dict):
        image_list = list(images.values())
    elif isinstance(images, list):
        image_list = images

    return {
        "review_id": r.get("review_id", ""),
        "rating": int(r.get("review_rating", 0) or 0),
        "text": r.get("review_text", ""),
        "reviewer_name": r.get("reviewer_name", ""),
        "reviewer_avatar": r.get("reviewer_avatar_url", ""),
        "is_verified": r.get("is_verified_purchase", False),
        "date": r.get("review_time", ""),
        "product_name": r.get("product_name", ""),
        "sku": r.get("sku_specification", ""),
        "country": r.get("review_country", ""),
        "images": image_list,
    }


def _get_image_url(img: dict) -> str:
    """Extract best URL from image object."""
    if not img:
        return ""
    urls = img.get("url_list", [])
    if urls:
        return urls[0]
    return ""


def _format_number(n: int) -> str:
    if n >= 1_000_000:
        return f"{n / 1_000_000:.1f}M"
    if n >= 1_000:
        return f"{n / 1_000:.1f}K"
    return str(n)
