import asyncio
import time
import aiohttp
from aiohttp import ClientError
from tenacity import retry, stop_after_attempt, wait_exponential, retry_if_exception_type
from sds_mng.util import logger, raise_for_status

API_URL = "https://pod-api.sdspod.com/pod/orders/page"
REQUEST_TIMEOUT = 30
DEFAULT_SLEEP = 5
DEFAULT_CONCURRENCY = 5

@retry(
    stop=stop_after_attempt(3),
    wait=wait_exponential(multiplier=1, min=1, max=8),
    retry=retry_if_exception_type(ClientError)
)
async def _fetch(access_token, filters=None, sleep=DEFAULT_SLEEP):
    headers = {"access-token": access_token or ""}
    filters = (filters or {}).copy()
    page = filters.pop("page", 1)
    size = filters.pop("size", 100)
    order_status_code = filters.pop("orderStatusCode", None)
    params = {
        "orderTimeRangeType": "2",
        "productionType": "2",
        "page": page,
        "size": size,
        "t": int(time.time() * 1000),
        **filters
    }
    if order_status_code:
        params["orderStatusCode"] = order_status_code

    async with aiohttp.ClientSession() as session:
        async with session.get(API_URL, headers=headers, params=params, timeout=aiohttp.ClientTimeout(total=REQUEST_TIMEOUT)) as resp:
            data = await resp.json()
            raise_for_status(resp, data)
            await asyncio.sleep(sleep)
            return data


async def fetch_orders(access_token, filters=None, limit=None, concurrency=DEFAULT_CONCURRENCY, sleep=DEFAULT_SLEEP):
    # 第一页
    first = await _fetch(access_token, {**(filters or {}), "page": 1, "size": 100}, sleep)
    total, orders = first.get("totalCount", 0), first.get("list", [])
    target = limit or total
    logger.info(f"已获取 {len(orders)}/{target} 条订单")

    if limit and limit <= len(orders):
        return {"totalCount": total, "fetchedCount": len(orders[:limit]), "list": orders[:limit]}

    # 计算剩余页数
    total_pages = (total + 99) // 100
    start_page = 2
    needed_pages = (limit - len(orders) + 99) // 100 if limit else total_pages - 1
    end_page = min(total_pages, start_page + needed_pages - 1) if needed_pages > 0 else 0
    page_numbers = list(range(start_page, end_page + 1)) if end_page >= start_page else []

    semaphore = asyncio.Semaphore(concurrency)

    async def fetch_page(page):
        async with semaphore:
            return await _fetch(access_token, {**(filters or {}), "page": page, "size": 100}, sleep)

    # 并发获取，实时进度
    if page_numbers:
        tasks = [fetch_page(p) for p in page_numbers]
        for coro in asyncio.as_completed(tasks):
            data = await coro
            orders.extend(data.get("list", []))
            fetched = min(len(orders), target) if limit else len(orders)
            logger.info(f"已获取 {fetched}/{target} 条订单")
            if limit and len(orders) >= limit:
                break

    if limit:
        orders = orders[:limit]

    return {"totalCount": total, "fetchedCount": len(orders), "list": orders}