import logging
import os
from typing import Optional

import aiohttp

logger = logging.getLogger(__name__)

BASE_URL = "https://api.shiznumber.com/api"


def _headers() -> dict:
    return {
        "Accept": "application/json",
        "Content-Type": "application/json",
        "X-API-KEY": os.getenv("SHIZNUMBER_API_KEY", ""),
    }


async def _request(
    method: str,
    path: str,
    json_data: Optional[dict] = None,
):
    key = os.getenv("SHIZNUMBER_API_KEY", "").strip()

    if not key:
        logger.error("SHIZNUMBER_API_KEY is not configured")
        return None

    url = f"{BASE_URL}/{path.lstrip('/')}"
    timeout = aiohttp.ClientTimeout(total=20)

    try:
        async with aiohttp.ClientSession(timeout=timeout) as session:
            async with session.request(
                method,
                url,
                headers=_headers(),
                json=json_data,
            ) as resp:
                raw = await resp.text()

                if resp.status >= 400:
                    logger.warning(
                        "ShizNumber API error [%s]: %s",
                        resp.status,
                        raw[:1000],
                    )
                    return {
                        "success": False,
                        "status": resp.status,
                        "error": raw[:1000],
                    }

                try:
                    return await resp.json(content_type=None)
                except Exception:
                    logger.error("Invalid JSON: %s", raw[:500])
                    return None

    except Exception as exc:
        logger.error("ShizNumber request failed: %s", exc)
        return None


async def get_user():
    return await _request("GET", "/user")


async def get_services():
    return await _request("GET", "/services")


async def get_countries():
    return await _request("GET", "/countries")


async def get_numbers():
    return await _request("GET", "/numbers")


async def get_service_numbers(service_slug: str):
    return await _request(
        "GET",
        f"/services/{service_slug}/numbers",
    )


async def get_country_numbers(country_slug: str):
    return await _request(
        "GET",
        f"/countries/{country_slug}/numbers",
    )


async def get_number(number_id: int):
    return await _request(
        "GET",
        f"/numbers/{int(number_id)}",
    )


async def buy_number(number_id: int):
    return await _request(
        "POST",
        f"/numbers/{int(number_id)}",
    )


async def get_order(order_id: int):
    return await _request(
        "GET",
        f"/orders/{int(order_id)}",
    )


async def cancel_order(order_id: int):
    return await _request(
        "PUT",
        f"/orders/{int(order_id)}/cancel",
    )


async def report_order(order_id: int):
    return await _request(
        "PUT",
        f"/orders/{int(order_id)}/report",
    )


async def recode_order(order_id: int):
    return await _request(
        "PUT",
        f"/orders/{int(order_id)}/recode",
    )

async def get_telegram_numbers_with_prices():
    """
    Load Telegram ShizNumber inventory for the shop.

    Only Shiz1 inventories are exposed.
    Selling price uses the existing account profit margin exactly once.
    No purchase request is made here.
    """
    from database.db import get_profit_margin
    from config import config

    data = await get_service_numbers("telegram")

    if not isinstance(data, list):
        return []

    margin_percent = await get_profit_margin(
        config.ACCOUNT_PROFIT_MARGIN_PERCENT
    )
    margin = float(margin_percent or 0) / 100.0

    result = []

    for item in data:
        if not isinstance(item, dict):
            continue

        # ShizNumber inventory ID
        try:
            number_id = int(item.get("id"))
        except (TypeError, ValueError):
            continue

        # Telegram Shiz1 only
        fa_name = str(
            item.get("fa_name")
            or item.get("name")
            or ""
        ).strip()

        if "shiz1" not in fa_name.lower():
            continue

        # Base/provider price
        raw_price = item.get(
            "price",
            item.get("amount", 0)
        )

        try:
            base_price = int(float(raw_price))
        except (TypeError, ValueError):
            continue

        # Inventory count
        raw_count = item.get("count", 0)

        try:
            count = int(
                float(
                    str(raw_count)
                    .replace(",", "")
                    .replace("،", "")
                )
            )
        except (TypeError, ValueError):
            count = 0

        # Country can be a dict or a plain string.
        country_data = item.get("country")

        if isinstance(country_data, dict):
            country_name = (
                country_data.get("fa_name")
                or country_data.get("name")
                or country_data.get("en_name")
                or fa_name
                or "نامشخص"
            )
        else:
            country_name = (
                country_data
                or item.get("country_name")
                or fa_name
                or "نامشخص"
            )

        country_name = str(country_name).strip()

        # Apply existing 30% account margin exactly once.
        final_price = int(
            base_price + (base_price * margin)
        )

        result.append({
            "provider": "shiznumber",
            "number_id": number_id,
            "range": str(number_id),
            "service_slug": "telegram",
            "country": country_name,
            "country_slug": item.get("slug"),
            "name": fa_name,
            "base_price": base_price,
            "final_price": final_price,
            "count": count,
            "in_stock": count > 0,
        })

    result.sort(
        key=lambda x: (
            x["country"],
            x["final_price"],
            x["number_id"],
        )
    )

    logger.info(
        "ShizNumber Telegram Shiz1 inventory loaded: %s items",
        len(result),
    )

    return result
