import hashlib
import requests
from flask import session, redirect, url_for, request
from functools import wraps

LOGIN_URL = "https://api.infi.cn/board/user/nc/accountLogin"
USER_API = "https://api.infi.cn/bsg/user/getMyInfo"

def infi_login(account, password):
    """使用英飞API登录"""
    try:
        login_data = {
            "account": account,
            "passwd": hashlib.md5(password.encode()).hexdigest(),
            "loginOriginType": 1
        }

        login_response = requests.post(
            LOGIN_URL,
            json=login_data,
            headers={"Content-Type": "application/json"},
            timeout=10
        )

        print(f"[debug] infi_login: LOGIN_URL status={login_response.status_code}")
        print(f"[debug] infi_login: LOGIN_URL body={login_response.text[:1000]}")

        if login_response.status_code != 200:
            return None, f"API请求失败，HTTP {login_response.status_code}"

        try:
            data = login_response.json()
        except ValueError:
            print("[debug] infi_login: 无法解析登录响应为 JSON", login_response.text[:1000])
            return None, "无法解析登录响应为 JSON"

        # 兼容不同的返回格式：优先从 obj.token 拿 token，其次尝试顶层 token 或 obj 为字符串的情况
        token = None
        if isinstance(data, dict):
            obj = data.get('obj')
            if isinstance(obj, dict) and obj.get('token'):
                token = obj.get('token')
            elif isinstance(obj, str) and obj:
                token = obj
            elif data.get('token'):
                token = data.get('token')

        if not token:
            # 如果存在 code/msg，把它们返回以便排查
            code = data.get('code') if isinstance(data, dict) else None
            msg = data.get('msg') if isinstance(data, dict) else None
            detail = f" code={code}" if code is not None else ""
            print(f"[debug] infi_login: 未找到 token，响应 data={data}")
            if msg:
                return None, f"登录失败: {msg}{detail}"
            return None, f"登录失败：未在响应中找到 token。响应: {data}"
        
        # 获取用户信息
        user_response = requests.post(
            USER_API,
            headers={
                "access-token": token,
                "Origin": "https://infi.cn",
                "Content-Type": "application/json"
            },
            timeout=10
        )

        print(f"[debug] infi_login: USER_API status={user_response.status_code}")
        print(f"[debug] infi_login: USER_API body={user_response.text[:1000]}")

        if user_response.status_code != 200:
            body = user_response.text[:1000]
            return None, f"获取用户信息失败，HTTP {user_response.status_code} 响应: {body}"

        try:
            user_data = user_response.json()
        except ValueError:
            print("[debug] infi_login: 无法解析用户信息响应为 JSON", user_response.text[:1000])
            return None, "无法解析用户信息响应为 JSON"

        # 兼容不同返回格式：服务端有时使用 code==0 表示成功
        if isinstance(user_data, dict) and user_data.get('code') is not None and user_data.get('code') not in (0, 200):
            print(f"[debug] infi_login: user_data indicates failure: {user_data}")
            return None, f"获取用户信息失败: {user_data.get('msg', '')} 响应: {user_data}"

        user_obj = None
        if isinstance(user_data, dict):
            user_obj = user_data.get('obj') or user_data

        return {
            'token': token,
            'user_info': user_obj
        }, None
        
    except Exception as e:
        # 针对网络/DNS 解析类错误返回更有帮助的提示
        msg = str(e)
        if 'NameResolutionError' in msg or 'Failed to resolve' in msg or 'Max retries exceeded' in msg:
            return None, (
                "网络错误：无法解析 api.infi.cn（DNS）。请检查网络连接、DNS 或代理设置。"
                " 可尝试命令：\n 1) `nslookup api.infi.cn`\n 2) `ping api.infi.cn`\n"
                " 或切换网络/使用 VPN、设置正确的 `HTTP(S)_PROXY` 环境变量。"
            )
        return None, f"登录异常: {msg}"

def login_required(f):
    """登录装饰器"""
    @wraps(f)
    def decorated_function(*args, **kwargs):
        if 'user_account' not in session:
            return redirect(url_for('login'))
        return f(*args, **kwargs)
    return decorated_function