#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
按用户抓取「自己的」邮箱发票（每个销售可用自己的邮箱授权码）
================================================================
与 fetch_invoices_mail.py 的区别：本脚本把工作区切到该用户自己的目录，
邮箱配置也取该用户自己的 `数据/邮箱配置.json`（0600），互不可见。

用法：
  fetch_user_mail.py --uid liuziyan --set-account 123456@qq.com --set-code <授权码>
  fetch_user_mail.py --uid liuziyan --test                 # 只测登录
  fetch_user_mail.py --uid liuziyan [--days 7] [--no-parse] # 抓取 → 解析 → 校验

安全：授权码只写入该用户工作区的 `数据/邮箱配置.json`（权限 600），
     不打印、不回传、不进任何外发内容。
"""
import argparse
import json
import os
import subprocess
import sys

HERE = os.path.dirname(os.path.abspath(__file__))
ROOT = os.path.dirname(HERE)                      # 报销助手/
sys.path.insert(0, HERE)
import expense_users as EU                        # noqa: E402

PY = sys.executable or '/usr/bin/python3'


def conf_path(home):
    return os.path.join(home, '数据', '邮箱配置.json')


def env_for(home):
    e = dict(os.environ)
    e['BAOYU_EXPENSE_HOME'] = home
    e['BAOYU_EXPENSE_SHARED'] = os.path.join(ROOT, '共享')
    return e


def default_conf():
    return {
        'imap_host': 'imap.qq.com', 'imap_port': 993, 'use_ssl': True,
        '账号': '', '授权码': '',
        '文件夹': ['INBOX'], '只抓未读': False, '抓取后标记已读': True,
        '附件后缀': ['.pdf', '.zip'], '主题关键词': [], '发件人白名单': [],
        '_说明': 'QQ 邮箱：设置 → 账户 → 开启 IMAP 服务 → 生成【授权码】，填到「授权码」。'
                 '其他邮箱请把 imap_host 改成对应服务器（如 imap.163.com / outlook.office365.com）。',
    }


def save_conf(home, account=None, code=None):
    p = conf_path(home)
    c = {}
    if os.path.exists(p):
        try:
            c = json.load(open(p, encoding='utf-8'))
        except Exception:
            c = {}
    base = default_conf()
    base.update(c or {})
    if account:
        base['账号'] = account.strip()
    if code:
        base['授权码'] = code.strip()
    os.makedirs(os.path.dirname(p), exist_ok=True)
    json.dump(base, open(p, 'w', encoding='utf-8'), ensure_ascii=False, indent=2)
    os.chmod(p, 0o600)
    return p, base


def run(script, args, env, label):
    fp = os.path.join(HERE, script)
    if not os.path.exists(fp):
        print('⚠️ 脚本不存在：%s' % fp)
        return 1
    r = subprocess.run([PY, fp] + list(args), env=env, capture_output=True, text=True)
    out = (r.stdout or '') + (r.stderr or '')
    for line in out.strip().splitlines()[-14:]:
        print('   %s' % line)
    if r.returncode != 0:
        print('   ⚠️ %s 退出码 %s' % (label, r.returncode))
    return r.returncode


def main(argv):
    ap = argparse.ArgumentParser()
    ap.add_argument('--uid', required=True, help='用户 uid（邮箱 @ 前，如 liuziyan）')
    ap.add_argument('--set-account', default='')
    ap.add_argument('--set-code', default='')
    ap.add_argument('--test', action='store_true')
    ap.add_argument('--days', type=int, default=0)
    ap.add_argument('--no-parse', action='store_true')
    a = ap.parse_args(argv)

    uid = EU.uid_of(a.uid, a.uid) or a.uid
    u = EU.get(uid)
    if not u:
        print('❌ 未找到用户 %s' % uid)
        return 2
    if not u.get('allow'):
        print('❌ 用户 %s 未开通报销助手' % uid)
        return 3
    home = EU.ensure_workspace(uid)
    env = env_for(home)
    print('👤 %s（%s）｜ 工作区 %s' % (u.get('name'), uid, home))

    if a.set_account or a.set_code:
        p, c = save_conf(home, a.set_account, a.set_code)
        print('✅ 邮箱配置已写入：%s（权限 600）' % p)
        print('   账号：%s ｜ 授权码：%s' % (c.get('账号') or '（空）',
                                            '已保存' if c.get('授权码') else '（空）'))
        if not (a.set_account and a.set_code):
            print('   ℹ️ 账号与授权码建议一起填写')
            return 0

    cp = conf_path(home)
    if not os.path.exists(cp):
        print('ℹ️ 该用户还没有邮箱配置：%s' % cp)
        print('   用 --set-account / --set-code 写入后即可抓取')
        return 0
    try:
        conf = json.load(open(cp, encoding='utf-8'))
    except Exception as e:
        print('❌ 配置读取失败：%s' % e)
        return 4
    if not conf.get('账号') or not conf.get('授权码'):
        print('ℹ️ 配置里账号或授权码为空（%s），跳过抓取' % cp)
        return 0

    args = []
    if a.days:
        args += ['--days', str(a.days)]
    if a.test:
        args += ['--test']
    print('📮 抓取邮箱 %s …' % conf.get('账号'))
    rc = run('fetch_invoices_mail.py', args, env, '抓取')
    if a.test or rc != 0:
        return rc
    if a.no_parse:
        return 0
    print('🔍 解析入库 …')
    run('invoice_parse.py', [], env, '解析')
    print('🧮 校验 …')
    run('invoice_check.py', [], env, '校验')
    print('✅ 完成（台账：%s）' % os.path.join(home, '数据', '报销台账.json'))
    return 0


if __name__ == '__main__':
    sys.exit(main(sys.argv[1:]))
