"""诊断微信 V3 商户证书/私钥/序列号是否匹配。用法: python manage.py wx_v3_pay_diag [--club xq]"""
import os

import requests
from django.core.management.base import BaseCommand

from jituan.constants import CLUB_ID_DEFAULT
from jituan.services.wechat_pay import (
    XQ_WX_PAY,
    get_wechat_v3_config,
    resolve_merchant_cert_serial,
    _load_pem_private_key,
    _public_keys_match,
)
from utils.wechat_v3 import build_authorization


class Command(BaseCommand):
    help = '诊断微信 V3 提现签名：私钥、证书序列号、商户号是否一致'

    def add_arguments(self, parser):
        parser.add_argument('--club', default=CLUB_ID_DEFAULT, help='俱乐部 ID：xq 或 xzj')

    def handle(self, *args, **options):
        club_id = (options.get('club') or CLUB_ID_DEFAULT).strip()
        cfg = get_wechat_v3_config(club_id)

        self.stdout.write('=== 微信 V3 配置诊断 ===')
        self.stdout.write(f"club_id      : {cfg.get('club_id')}")
        self.stdout.write(f"APPID        : {cfg.get('APPID')}")
        self.stdout.write(f"MCHID        : {cfg.get('MCHID')}  (期望 {XQ_WX_PAY['mch_id']})")
        self.stdout.write(f"CERT_SERIAL  : {cfg.get('CERT_SERIAL_NO')}")
        self.stdout.write(f"API_V3_KEY   : len={len(cfg.get('API_V3_KEY') or '')}")
        key_path = cfg.get('PRIVATE_KEY_PATH') or ''
        self.stdout.write(f"PRIVATE_KEY  : {key_path}")
        self.stdout.write(f"key_exists   : {os.path.isfile(key_path)}")

        cert_dir = os.path.dirname(os.path.abspath(key_path)) if key_path else ''
        self.stdout.write(f"cert_dir     : {cert_dir}")
        if cert_dir and os.path.isdir(cert_dir):
            self.stdout.write('cert_dir files:')
            for name in sorted(os.listdir(cert_dir)):
                if name.lower().endswith('.pem'):
                    self.stdout.write(f'  - {name}')

        serial_from_match = resolve_merchant_cert_serial(key_path, '')
        self.stdout.write(f"matched_serial: {serial_from_match or '(未匹配到证书)'}")

        if key_path and os.path.isfile(key_path):
            try:
                private_key = _load_pem_private_key(key_path)
                self.stdout.write('private_key  : 加载成功')

                from cryptography import x509
                from cryptography.hazmat.backends import default_backend

                tested = []
                for fname in sorted(os.listdir(cert_dir)):
                    if not fname.lower().endswith('.pem'):
                        continue
                    if fname.lower() in ('apiclient_key.pem',):
                        continue
                    cert_path = os.path.join(cert_dir, fname)
                    tested.append(fname)
                    try:
                        with open(cert_path, 'rb') as f:
                            data = f.read()
                        if b'PRIVATE KEY' in data:
                            self.stdout.write(f'  {fname}: 是私钥，跳过')
                            continue
                        cert = x509.load_pem_x509_certificate(data, default_backend())
                        serial = format(cert.serial_number, 'X').upper()
                        matched = _public_keys_match(private_key, cert.public_key())
                        self.stdout.write(
                            f'  {fname}: X509证书 serial={serial} 与私钥匹配={matched}'
                        )
                    except Exception as exc:
                        self.stdout.write(f'  {fname}: 非X509商户证书 ({exc})')

                if 'apiclient_cert.pem' not in tested:
                    self.stdout.write(self.style.ERROR(
                        '\n缺少 apiclient_cert.pem！'
                        '\n请到微信商户平台(1747846572) → 账户中心 → API安全 → 申请API证书'
                        '\n下载证书包，将 apiclient_cert.pem 放到目录:'
                        f'\n  {cert_dir}'
                        '\n当前目录只有 apiclient_key.pem，没有商户证书，所以签名必然失败。'
                        '\npub_key.pem 是微信支付平台公钥，不能代替 apiclient_cert.pem。'
                    ))
            except Exception as exc:
                self.stdout.write(self.style.ERROR(f'私钥/证书检查失败: {exc}'))

        # 试探请求：查一个不存在的单号，仅验证签名是否通过（404=签名OK，401 SIGN_ERROR=签名失败）
        url = 'https://api.mch.weixin.qq.com/v3/fund-app/mch-transfer/transfer-bills/out-bill-no/WX_V3_DIAG_TEST'
        auth = build_authorization('GET', url, '', club_id=club_id)
        try:
            resp = requests.get(
                url,
                headers={
                    'Authorization': auth,
                    'Accept': 'application/json',
                    'User-Agent': 'Mozilla/5.0',
                },
                timeout=10,
            )
            self.stdout.write(f"\n探针 HTTP {resp.status_code}: {resp.text[:300]}")
            if resp.status_code == 401:
                self.stdout.write(self.style.ERROR(
                    '签名仍失败：请确认服务器 apiclient_key.pem / apiclient_cert.pem '
                    '是商户号 1747846572 在微信商户平台下载的那一对'
                ))
            elif resp.status_code in (404, 200):
                self.stdout.write(self.style.SUCCESS('签名已通过（404/200 表示微信接受了商户签名）'))
        except requests.RequestException as exc:
            self.stdout.write(self.style.ERROR(f'探针请求失败: {exc}'))
