from __future__ import annotations

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


def GET_并发(
    url_list: Sequence[str],
    params_list: Optional[Sequence[Optional[Dict[str, 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 GET 请求，返回与输入等长的响应列表。

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

    Args:
        url_list: URL 列表。
        params_list: 与 url_list 等长的 params 列表；为 None 时全部不带 params。
        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 结果

    if params_list is not None and len(params_list) != len(url_list):
        params_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

        params = params_list[idx] if params_list is not None else None

        for attempt in range(最大重试次数):
            try:
                resp = requests.get(
                    url=url,
                    params=params,
                    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 结果