"""
imap_inbox_test.py — IMAP 自动进箱测试 (PHPMailer Pro 同款逻辑的 Python 移植)
================================================================
用法:
  imap_check_inbox(imap_cfg, proxy, test_token)
    imap_cfg: {'host','port','user','pwd','secure': ssl/starttls/none}
    proxy:    可选 {'host','port','user','pwd'} SOCKS5 (代理池直连IMAP)
    test_token: 测试邮件主题里的唯一标记
  返回: {'ok', 'placement': 'inbox'/'spam'/'not_found', 'folders_checked', 'msg'}
"""
import socket
import time

SPAM_FOLDER_HINTS = ('spam', 'junk', 'bulk', 'quarantine', '迷惑', 'ゴミ', 'スパム')
INBOX_HINTS = ('inbox', '受信トレイ', '收件箱')


def _apply_proxy(proxy):
    """全局 SOCKS5 代理 (PySocks monkeypatch socket)"""
    if not proxy or not proxy.get('host'):
        return
    try:
        import socks
        socks.set_default_proxy(
            socks.SOCKS5,
            str(proxy.get('host')),
            int(proxy.get('port') or 1080),
            username=proxy.get('user') or None,
            password=proxy.get('pwd') or None,
        )
        socket.socket = socks.socksocket
    except Exception:
        pass


def _is_spam_folder(name):
    n = (name or '').lower()
    return any(h in n for h in SPAM_FOLDER_HINTS)


def _is_inbox_folder(name):
    n = (name or '').lower()
    return n == 'inbox' or any(h in n for h in INBOX_HINTS)


def _parse_folder_list(data):
    """imaplib LIST 结果解析 → 文件夹名列表 (自动解码 MUTF7/中文)"""
    import re
    folders = []
    for line in data or []:
        try:
            if isinstance(line, bytes):
                line = line.decode('utf-7', 'replace') if b'&' in line else line.decode('utf-8', 'replace')
            m = re.search(r'"([^"]*)"\s*(?:\r?\n)?$', str(line))
            if m:
                name = m.group(1).strip('"').strip()
                if name:
                    folders.append(name)
        except Exception:
            continue
    return folders


def imap_check_inbox(imap_cfg, proxy, test_token, timeout=25):
    """连 IMAP 检查 test_token 落在哪个文件夹
    返回 {'ok': bool, 'placement': 'inbox'/'spam'/'not_found', 'folders_checked': [..], 'msg': str}
    """
    result = {'ok': False, 'placement': 'not_found', 'folders_checked': [], 'msg': ''}
    host = str(imap_cfg.get('host') or '').strip()
    if not host:
        result['msg'] = 'IMAP服务器未填'
        return result
    port = int(imap_cfg.get('port') or 993)
    user = str(imap_cfg.get('user') or '')
    pwd = str(imap_cfg.get('pwd') or '')
    secure = str(imap_cfg.get('secure') or 'ssl').lower()
    _apply_proxy(proxy)

    try:
        import imaplib
        if secure == 'ssl':
            M = imaplib.IMAP4_SSL(host, port, timeout=timeout)
        else:
            M = imaplib.IMAP4(host, port, timeout=timeout)
        try:
            resp = M.login(user, pwd)
        except imaplib.IMAP4.error:
            if secure == 'starttls':
                try:
                    M.starttls()
                except Exception:
                    pass
                resp = M.login(user, pwd)
            else:
                raise
        if resp and resp[0] != 'OK':
            result['msg'] = 'IMAP登录失败: ' + str(resp)
            try: M.logout()
            except Exception: pass
            return result

        typ, data = M.list()
        folders = _parse_folder_list(data) if typ == 'OK' else []
        result['folders_checked'] = folders[:30]

        # 优先查垃圾箱类, 再查收件箱 (垃圾箱命中直接判定)
        spam_folders = [f for f in folders if _is_spam_folder(f)]
        inbox_folders = [f for f in folders if _is_inbox_folder(f)]
        search_order = spam_folders + inbox_folders
        # 兜底: 若没识别出标准文件夹, 全查
        if not search_order:
            search_order = folders

        token_quoted = str(test_token).replace('"', '').strip()
        for folder in search_order:
            try:
                st, _cnt = M.select(folder, readonly=True)
                if st != 'OK':
                    continue
                typ2, data2 = M.search(None, '(HEADER Subject "%s")' % token_quoted)
                hit_ids = []
                if typ2 == 'OK' and data2 and data2[0]:
                    hit_ids = data2[0].decode('utf-8', 'replace').split()
                if not hit_ids:
                    typ3, data3 = M.search(None, '(BODY "%s")' % token_quoted)
                    if typ3 == 'OK' and data3 and data3[0]:
                        hit_ids = data3[0].decode('utf-8', 'replace').split()
                if hit_ids:
                    if _is_spam_folder(folder):
                        result['placement'] = 'spam'
                    elif _is_inbox_folder(folder):
                        result['placement'] = 'inbox'
                    else:
                        result['placement'] = 'other'
                    result['ok'] = True
                    result['msg'] = '测试邮件找到: 文件夹「' + folder + '」'
                    break
            except Exception:
                continue
        try:
            M.logout()
        except Exception:
            pass
        if not result['ok']:
            result['msg'] = '未在已检查的文件夹中找到测试邮件 (可能还在投递中/被其他文件夹接收)'
            result['ok'] = True  # 连接检查本身成功, 只是没找到
        return result
    except Exception as e:
        result['msg'] = 'IMAP连接失败: ' + str(e)[:120]
        return result
