#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from __future__ import annotations

import re
import time
from typing import Optional

import requests

from app_logger import get_logger
from app_security import is_safe_outbound_url

logger = get_logger("proxy")


def validate_ip_port(ip_port_str: str) -> bool:
    """验证IP:PORT格式是否有效（含范围校验）。"""
    pattern = re.compile(r"^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3}):(\d{1,5})$")
    match = pattern.match(ip_port_str or "")
    if not match:
        return False

    for i in range(1, 5):
        octet = int(match.group(i))
        if octet < 0 or octet > 255:
            return False

    port = int(match.group(5))
    return 1 <= port <= 65535


def get_proxy_from_api(api_url: str, max_retries: int = 3) -> Optional[str]:
    """从API获取代理IP（支持重试）。"""
    ip_port_pattern = re.compile(r"^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}:\d{1,5}$")
    max_retries = max(1, int(max_retries or 1))

    if not is_safe_outbound_url(api_url):
        logger.warning("代理API地址不可用或不安全，已拒绝请求")
        return None

    for attempt in range(max_retries):
        try:
            response = requests.get(api_url, timeout=10)
            if response.status_code == 200:
                text = response.text.strip()

                # 尝试解析JSON响应
                try:
                    import json

                    data = json.loads(text)
                    if isinstance(data, dict):
                        if data.get("status") not in (200, 0, None):
                            error_msg = data.get("msg", data.get("message", "未知错误"))
                            logger.warning(f"代理API返回错误: {error_msg} (尝试 {attempt + 1}/{max_retries})")
                            if attempt < max_retries - 1:
                                time.sleep(1)
                            continue
                        ip_port = data.get("ip") or data.get("proxy") or data.get("data")
                        if ip_port:
                            text = str(ip_port).strip()
                except Exception:
                    pass

                if ip_port_pattern.match(text) and validate_ip_port(text):
                    proxy_server = f"http://{text}"
                    logger.info(f"获取代理成功: {proxy_server} (尝试 {attempt + 1}/{max_retries})")
                    return proxy_server

                logger.warning(f"代理格式或范围无效: {text[:50]} (尝试 {attempt + 1}/{max_retries})")
            else:
                logger.warning(f"获取代理失败: HTTP {response.status_code} (尝试 {attempt + 1}/{max_retries})")
        except Exception as e:
            logger.warning(f"获取代理异常: {str(e)} (尝试 {attempt + 1}/{max_retries})")

        if attempt < max_retries - 1:
            time.sleep(1)

    logger.warning(f"获取代理失败，已重试 {max_retries} 次，将不使用代理继续")
    return None
