"""
TinyDataPay Python SDK
"""

import hashlib
import json
import time
from urllib.parse import urlencode

import requests


class TinyDataPay:
    """TinyDataPay 支付客户端"""

    def __init__(self, api_url: str, safe_key: str):
        self.api_url = api_url.rstrip("/")
        self.safe_key = safe_key

    # ========== 签名 ==========

    def generate_sign(self, params: dict) -> str:
        """生成 MD5 签名"""
        # 1. 过滤空值和 sign 字段，按 key 排序
        filtered = {k: v for k, v in params.items() if k != "sign" and v != ""}
        sorted_keys = sorted(filtered.keys())

        # 2. 拼接: key1=value1&key2=value2&key=safe_key
        sign_str = "&".join(f"{k}={filtered[k]}" for k in sorted_keys)
        sign_str += f"&key={self.safe_key}"

        # 3. MD5 大写
        return hashlib.md5(sign_str.encode("utf-8")).hexdigest().upper()

    def verify_sign(self, params: dict) -> bool:
        """验证签名"""
        received_sign = params.get("sign", "")
        if not received_sign:
            return False
        return self.generate_sign(params) == received_sign

    # ========== 创建订单 ==========

    def create_order(
        self,
        merchant_order_id: str,
        amount: str,
        currency: str = "CNY",
        product_name: str = "",
        notify_url: str = "",
        redirect_url: str = "",
    ) -> dict:
        """
        创建支付订单

        :return: {"order_no": "PAYxxx", "amount": "10.00", "payment_url": "https://..."}
        :raises Exception: 创建失败
        """
        params = {
            "merchant_order_id": merchant_order_id,
            "amount": amount,
            "currency": currency,
            "product_name": product_name,
        }
        if notify_url:
            params["notify_url"] = notify_url
        if redirect_url:
            params["redirect_url"] = redirect_url

        params["sign"] = self.generate_sign(params)

        resp = requests.post(
            f"{self.api_url}/api/v1/payment/create",
            json=params,
            timeout=10,
        )
        result = resp.json()

        if result.get("code") != 0:
            raise Exception(f"创建订单失败: {result.get('message')}")

        return result["data"]

    # ========== 查询订单 ==========

    def query_order(self, order_no: str) -> dict:
        """
        查询订单状态

        :return: {"order_no": "PAYxxx", "status": "paid", "pay_type": "ALIPAY", ...}
        """
        resp = requests.get(
            f"{self.api_url}/api/v1/payment/status",
            params={"order_no": order_no},
            timeout=10,
        )
        result = resp.json()

        if result.get("code") != 0:
            raise Exception(f"查询失败: {result.get('message')}")

        return result["data"]

    # ========== 解析回调 ==========

    def parse_callback(self, params: dict) -> dict:
        """
        解析并验证回调参数

        :param params: 回调 GET/POST 参数 dict
        :return: 验证通过返回回调数据
        :raises Exception: 签名验证失败
        """
        if not self.verify_sign(params):
            raise Exception("签名验证失败")

        return {
            "order_no": params.get("order_no", ""),
            "merchant_order_id": params.get("merchant_order_id", ""),
            "amount": params.get("amount", ""),
            "status": params.get("status", ""),
            "pay_type": params.get("pay_type", ""),
        }


# ========== 使用示例 ==========

if __name__ == "__main__":
    client = TinyDataPay("https://pay.tinydata.cc", "your_safe_key")

    # 创建订单
    order = client.create_order(
        merchant_order_id=f"TEST{int(time.time())}",
        amount="10.00",
        currency="CNY",
        product_name="测试商品",
        notify_url="https://your-site.com/callback",
    )
    print(f"订单号: {order['order_no']}")
    print(f"支付链接: {order['payment_url']}")

    # 查询订单
    status = client.query_order(order["order_no"])
    print(f"状态: {status['status']}")
