"""
http工具类
"""

from pathlib import Path
from functools import wraps

import requests
from loguru import logger
from joblib import Parallel, delayed


def handle_exception(func):
    """异常处理包装类"""

    @wraps(func)
    def wrapper(*args, **kwargs):
        try:
            return func(*args, **kwargs)
        except requests.exceptions.HTTPError as e:
            logger.error(f"请求失败，状态码: {e.response.status_code}")
            return None
        except requests.exceptions.Timeout as e:
            logger.error(f"请求超时: {e}")
            return None
        except requests.exceptions.RequestException as e:
            logger.error(f"发生错误: {e}")
            return None
        except Exception as e:
            logger.error(f"发生错误: {e}")
            return None

    return wrapper


def __get_headers(token: str):
    return {
        "Access-Token": token,
        "User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36",
    }


@handle_exception
def get_json(url: str, session: requests.Session | None = None, proxies=None):
    """获取json"""
    response = (session or requests).get(url, proxies=proxies)
    response.raise_for_status()
    if response.status_code != 200:
        return None
    return response.json()


@handle_exception
def get_content(url: str, session: requests.Session | None = None) -> bytes:
    """获取内容"""
    response = (session or requests).get(url)
    response.raise_for_status()
    return response.content


def write_content(url: str, path: Path, session: requests.Session | None = None):
    """写入内容"""
    while (content := get_content(url, session)) is None:
        continue
    with path.open("wb") as f:
        f.write(content)


def batch_download(urls: dict[Path, str], session: requests.Session | None = None):
    """批量下载"""
    Parallel(n_jobs=16, backend="threading")(
        delayed(write_content)(url, write_path, session)
        for write_path, url in urls.items()
    )


@handle_exception
def get_task_info(
    task_id: str,
    token: str,
    domain: str,
    session: requests.Session | None = None,
    host: str | None = None,
):
    """请求task_info信息"""
    url = f"{domain}/api/v2/task/get/task-info"
    headers = __get_headers(token)
    if host:
        headers["Host"] = host
    params = {"taskId": task_id}
    response = (session or requests).post(url, headers=headers, json=params)
    response.raise_for_status()
    if response.status_code != 200:
        return None
    return response.json()


@handle_exception
def get_item_info(
    item_id: str,
    token: str,
    domain: str,
    session: requests.Session | None = None,
    host: str | None = None,
):
    """item 请求信息"""
    url = f"{domain}/api/v2/item/get-item-info"
    headers = __get_headers(token)
    if host:
        headers["Host"] = host
    params = {"itemId": item_id}
    response = (session or requests).post(url, headers=headers, json=params)
    response.raise_for_status()
    if response.status_code != 200:
        return None
    return response.json()


@handle_exception
def find_labels(
    task_id: str,
    item_id: str,
    token: str,
    domain: str,
    session: requests.Session | None = None,
    host: str | None = None,
):
    """请求标签信息"""
    url = f"{domain}/api/v2/label/find-labels"
    headers = __get_headers(token)
    if host:
        headers["Host"] = host
    params = {"taskId": task_id, "itemId": item_id}
    response = (session or requests).post(url, headers=headers, json=params)
    response.raise_for_status()
    if response.status_code != 200:
        return None
    return response.json()
