import requests
import json
import pymssql
from datetime import datetime

# delivery 平台统一异步结果通知接口（与 ES 海牙 030 / 意大利 EPR 同模式）
# 仅 DataSource='api' 的记录在结果落库后追加调用；runner 可传参覆盖（受理时 bizParam.callback_url 优先）
DEFAULT_RESULT_CALLBACK_URL = "http://192.168.1.211:8080/delivery/rpa/callback"


def get_field(row, name):
    """按列名大小写不敏感取值（兼容 pymssql as_dict 键名大小写差异）"""
    if not row:
        return None
    for key, value in row.items():
        if key.lower() == name.lower():
            return value
    return None


def parse_biz_param(row):
    """解析行内 biz_param JSON；失败时回退为行内字段构造的最小 bizParam"""
    raw = get_field(row, 'biz_param')
    if isinstance(raw, str) and raw:
        try:
            parsed = json.loads(raw)
            if isinstance(parsed, dict):
                return parsed
        except json.JSONDecodeError:
            pass
    return {
        'BusinessSerialNumber': get_field(row, 'code'),
        'source_record_id': get_field(row, 'source_record_id'),
    }


def resolve_notification_url(row, delivery_callback_url):
    """通知地址优先级：受理 bizParam.callback_url > runner 传参 > 默认 delivery 地址"""
    biz = parse_biz_param(row)
    if isinstance(biz, dict) and biz.get('callback_url'):
        return biz['callback_url']
    if delivery_callback_url:
        return delivery_callback_url
    return DEFAULT_RESULT_CALLBACK_URL


def send_async_result_notification(url, payload):
    """
    发送 delivery 平台统一异步结果通知
    best-effort：2xx 视为送达，单次不重试，失败不影响主流程
    """
    try:
        headers = {'Content-Type': 'application/json; charset=utf-8'}
        response = requests.post(
            url,
            data=json.dumps(payload, ensure_ascii=False),
            headers=headers,
            timeout=10
        )
        print(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] 异步结果通知 HTTP {response.status_code}: {url}")
        return 200 <= response.status_code < 300
    except Exception as e:
        print(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] 异步结果通知失败（不影响主流程）: {e}")
        return False


def query_record_source(record_id, db_ip, db_port, db_username, db_password, database):
    """
    查询记录来源（DataSource / biz_param 等）
    表结构缺少新列（旧库）时返回空 dict，调用方按 source 行处理
    """
    conn = None
    cursor = None
    try:
        conn = pymssql.connect(
            server=db_ip,
            port=db_port,
            user=db_username,
            password=db_password,
            database=database,
            charset='utf8',
            as_dict=True
        )
        cursor = conn.cursor()
        cursor.execute(
            "SELECT DataSource, biz_param, code, source_record_id "
            "FROM uk_vat_register WHERE id = %s",
            (record_id,)
        )
        row = cursor.fetchone()
        return row if row else {}
    except pymssql.Error as e:
        print(f"查询记录来源失败（按 source 行处理）: {e}")
        return {}
    finally:
        if cursor:
            cursor.close()
        if conn:
            conn.close()


def send_callback_request(
    callback_url,
    callback_token,
    vat_business_record_id,
    mtd_account,
    mtd_password,
    mtd_key,
    reg_receipt,
    reg_receipt_number,
    other_file,
    record_id,
    db_ip,
    db_port,
    db_username,
    db_password,
    database,
    delivery_callback_url=None
):
    """
    发送 HTTP POST 请求并更新数据库
    注册结果判定维持原流程（老 open-token 回调响应 succeeded 字段）；
    仅 DataSource='api' 的行在结果落库后追加 delivery 统一异步结果通知。

    参数:
        callback_url (str): 老 open-token 回调 URL
        callback_token (str): 认证token
        vat_business_record_id (str): VAT业务记录ID
        mtd_account (str): MTD账号
        mtd_password (str): MTD密码
        mtd_key (str): MTD密钥
        reg_receipt (str or list): 注册收据（字符串或列表）
        reg_receipt_number (str): 注册收据编号
        other_file (str or list): 其他文件（字符串或列表）
        record_id (int): 数据库记录ID
        db_ip (str): 数据库IP地址
        db_port (int): 数据库端口
        db_username (str): 数据库用户名
        db_password (str): 数据库密码
        database (str): 数据库名称
        delivery_callback_url (str, optional): delivery 统一异步结果通知地址，
            缺省用 DEFAULT_RESULT_CALLBACK_URL；仅 DataSource='api' 行调用

    返回:
        dict: {
            'success': bool,
            'http_code': int,
            'response_data': dict,
            'register_status': int,
            'error': str
        }
    """

    # 转换 reg_receipt 为数组
    if isinstance(reg_receipt, str):
        reg_receipt_array = [reg_receipt] if reg_receipt else []
    elif isinstance(reg_receipt, list):
        reg_receipt_array = reg_receipt
    else:
        reg_receipt_array = []

    # 转换 other_file 为数组
    if isinstance(other_file, str):
        other_file_array = [other_file] if other_file else []
    elif isinstance(other_file, list):
        other_file_array = other_file
    else:
        other_file_array = []

    # 记录来源：仅用于决定结果落库后是否追加 delivery 异步结果通知
    row_source = query_record_source(record_id, db_ip, db_port, db_username, db_password, database)
    data_source = str(get_field(row_source, 'DataSource') or 'source').lower()

    # 构建请求数据
    data = {
        "vatBusinessRecordId": vat_business_record_id,
        "mtdInfo": {
            "mtdAccount": mtd_account,
            "mtdPassword": mtd_password,
            "mtdKey": mtd_key
        },
        "regReceipt": reg_receipt_array,
        "regReceiptNumber": reg_receipt_number,
        "otherFile": other_file_array
    }

    # 转换为JSON字符串
    json_data = json.dumps(data, ensure_ascii=False)

    # 设置请求头
    headers = {
        'open-token': callback_token,
        'Content-Type': 'application/json-patch+json',
        'Content-Length': str(len(json_data.encode('utf-8')))
    }

    result = {
        'success': False,
        'http_code': None,
        'response_data': None,
        'register_status': 3,  # 默认为失败
        'error': None
    }

    try:
        # 发送POST请求
        print(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] 发送请求到: {callback_url}")
        print(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] 请求数据: {json_data}")

        response = requests.post(
            callback_url,
            data=json_data,
            headers=headers,
            timeout=30
        )

        # 获取响应信息
        http_code = response.status_code
        result['http_code'] = http_code

        print(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] HTTP状态码: {http_code}")

        # 解析响应JSON
        try:
            response_json = response.json()
            result['response_data'] = response_json
            print(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] 响应: {json.dumps(response_json, ensure_ascii=False)}")

            # 判断注册状态
            # 成功条件: HTTP状态码为200 且 succeeded字段为true
            if http_code == 200 and response_json.get('succeeded') == True:
                result['register_status'] = 2  # 成功
                result['success'] = True
                print(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] 注册成功")
            else:
                result['register_status'] = 3  # 失败
                result['error'] = response_json.get('message', '注册失败')
                print(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] 注册失败: {result['error']}")

        except json.JSONDecodeError as e:
            result['error'] = f"响应JSON解析失败: {str(e)}"
            print(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] 错误: {result['error']}")
            print(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] 原始响应: {response.text}")
            return result

        # 更新数据库
        try:
            update_database(
                db_ip,
                db_port,
                db_username,
                db_password,
                database,
                record_id,
                json_data,
                result['register_status'],
                mtd_account,
                mtd_password,
                mtd_key
            )
            print(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] 数据库更新成功, 记录ID: {record_id}, 状态: {result['register_status']}")
        except Exception as e:
            result['error'] = f"数据库更新失败: {str(e)}"
            print(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] 错误: {result['error']}")
            result['success'] = False
            return result

        # 仅 api 行：结果落库后追加 delivery 统一异步结果通知（best-effort）
        if data_source == 'api':
            notify_url = resolve_notification_url(row_source, delivery_callback_url)
            biz_param = parse_biz_param(row_source)
            if result['register_status'] == 2:
                payload = {
                    'code': 200,
                    'msg': 'success',
                    'ProcessMode': 'async',
                    'data': {
                        'record_id': record_id,
                        'status': 'success',
                        'reg_receipt_number': reg_receipt_number,
                        'reg_receipt': reg_receipt_array,
                        'other_file': other_file_array,
                    },
                    'bizParam': biz_param,
                }
            else:
                payload = {
                    'code': 500,
                    'msg': 'failed',
                    'ProcessMode': 'async',
                    'data': {
                        'record_id': record_id,
                        'status': 'failed',
                        'error': result['error'] or '注册失败',
                    },
                    'bizParam': biz_param,
                }
            send_async_result_notification(notify_url, payload)

        return result

    except requests.exceptions.Timeout:
        result['error'] = "请求超时"
        print(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] 错误: {result['error']}")
        return result
    except requests.exceptions.RequestException as e:
        result['error'] = f"请求异常: {str(e)}"
        print(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] 错误: {result['error']}")
        return result
    except Exception as e:
        result['error'] = f"未知错误: {str(e)}"
        print(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] 错误: {result['error']}")
        return result


def update_database(db_ip, db_port, db_username, db_password, database,
                    record_id, submit_data, register_status,
                    mtd_account=None, mtd_password=None, mtd_key=None):
    """
    更新数据库记录

    参数:
        db_ip (str): 数据库IP地址
        db_port (int): 数据库端口
        db_username (str): 数据库用户名
        db_password (str): 数据库密码
        database (str): 数据库名称
        record_id (int): 记录ID
        submit_data (str): 提交的JSON数据
        register_status (int): 注册状态 (2-成功, 3-失败)
        mtd_account (str, optional): MTD账号
        mtd_password (str, optional): MTD密码
        mtd_key (str, optional): MTD密钥
    """
    conn = None
    cursor = None

    try:
        # 连接数据库
        conn = pymssql.connect(
            server=db_ip,
            port=db_port,
            user=db_username,
            password=db_password,
            database=database,
            charset='utf8'
        )
        cursor = conn.cursor()

        # 执行更新
        sql = """
            UPDATE uk_vat_register
            SET submit_backup_data = %s,
                registration_status = %s,
                mtd_account = %s,
                mtd_password = %s,
                mtd_key = %s,
                updated_date = GETDATE()
            WHERE id = %s
        """
        cursor.execute(sql, (
            submit_data,
            register_status,
            mtd_account,
            mtd_password,
            mtd_key,
            record_id
        ))
        conn.commit()

    finally:
        if cursor:
            cursor.close()
        if conn:
            conn.close()
