from __future__ import annotations

from typing import Any, Dict, List, Mapping, Optional, Sequence, Union
import time
import requests
from concurrent.futures import ThreadPoolExecutor, as_completed


def POST_并发(
    url_list: Sequence[str],
    data_list: Optional[Sequence[Optional[Union[Mapping[str, Any], bytes, str]]]] = None,
    json_list: Optional[Sequence[Optional[Any]]] = None,
    headers: Optional[Dict[str, str]] = None,
    cookies: Optional[Dict[str, str]] = None,
    timeout: Union[int, float] = 10,
    allow_redirects: bool = True,
    verify: bool = True,
    proxies: Optional[Dict[str, str]] = None,
    max_workers: int = 20,
) -> List[Optional[requests.Response]]:
    """
    并发发送多条 HTTP POST 请求，返回与输入等长的响应列表。

    设计原则：
        - 并发数量可控，默认最大 20 个通道
        - 返回列表与 url_list 等长，顺序严格一致
        - 单条请求失败返回 None，不影响其他请求
        - 内置固定重试机制：失败等待 1 秒，最多 3 次（固定策略）
        - 等待所有任务完成后统一返回结果
        - 发送内容约定：json 优先，其次 data

    Args:
        url_list: URL 列表。
        data_list:
            与 url_list 等长的 data 列表（非 JSON 场景）。为 None 表示全部不带 data。
        json_list:
            与 url_list 等长的 json 列表（JSON 场景）。为 None 表示全部不带 json。
            注意：单条请求中 json 不为 None 时优先使用 json。
        headers: 所有请求共用的请求头。
        cookies: 所有请求共用的 Cookie。
        timeout: 单次请求超时（秒）。
        allow_redirects: 是否跟随重定向。
        verify: 是否验证 HTTPS 证书。
        proxies: 代理配置。
        max_workers: 最大并发数量，默认 20。

    Returns:
        List[Optional[requests.Response]]:
            与输入等长的结果列表。
            成功为 Response，失败为 None。
    """
    结果: List[Optional[requests.Response]] = [None] * len(url_list)

    if not isinstance(url_list, (list, tuple)) or len(url_list) == 0:
        return 结果

    # 长度不匹配就按“不提供该列表”处理，避免新手被 ValueError 教做人
    if data_list is not None and len(data_list) != len(url_list):
        data_list = None
    if json_list is not None and len(json_list) != len(url_list):
        json_list = None

    最大重试次数 = 3
    失败等待秒数 = 1.0

    def _单条请求(idx: int) -> tuple[int, Optional[requests.Response]]:
        url = url_list[idx]
        if not isinstance(url, str) or not url.strip():
            return idx, None

        data = data_list[idx] if data_list is not None else None
        js = json_list[idx] if json_list is not None else None

        for attempt in range(最大重试次数):
            try:
                if js is not None:
                    resp = requests.post(
                        url=url,
                        json=js,
                        headers=headers,
                        cookies=cookies,
                        timeout=timeout,
                        allow_redirects=allow_redirects,
                        verify=verify,
                        proxies=proxies,
                    )
                    return idx, resp

                resp = requests.post(
                    url=url,
                    data=data,
                    headers=headers,
                    cookies=cookies,
                    timeout=timeout,
                    allow_redirects=allow_redirects,
                    verify=verify,
                    proxies=proxies,
                )
                return idx, resp

            except Exception:
                if attempt < 最大重试次数 - 1:
                    time.sleep(失败等待秒数)
                else:
                    return idx, None

        return idx, None

    实际通道数量 = min(max_workers, len(url_list))
    if 实际通道数量 <= 0:
        实际通道数量 = 1

    with ThreadPoolExecutor(max_workers=实际通道数量) as executor:
        futures = [executor.submit(_单条请求, i) for i in range(len(url_list))]
        for future in as_completed(futures):
            idx, resp = future.result()
            结果[idx] = resp

    return 结果