# vorto_utils/mapay.py - MaPay payment client
import hashlib
import requests


class MaPayClient:
    """MaPay payment client.

    Usage:
        client = MaPayClient()
        client = MaPayClient(gateway='https://pay.example.com', pid='1001', key='your_key')

        result = client.create_order(8.88, 'alipay', 'order_123', '牛卡福-1月')
        is_paid = client.is_paid('order_123')
    """

    def __init__(self, gateway=None, pid=None, key=None, notify_url=None, return_url=None):
        if any(v is None for v in [gateway, pid, key, notify_url, return_url]):
            try:
                import middleware
                if gateway is None:
                    gateway = middleware.bucketGet('s_vorto', 'ma_pay_gateway') or ''
                if pid is None:
                    pid = middleware.bucketGet('s_vorto', 'ma_pay_pid') or ''
                if key is None:
                    key = middleware.bucketGet('s_vorto', 'ma_pay_key') or ''
                if notify_url is None:
                    notify_url = middleware.bucketGet('s_vorto', 'ma_pay_notify_url') or ''
                if return_url is None:
                    return_url = middleware.bucketGet('s_vorto', 'ma_pay_return_url') or ''
            except ImportError:
                gateway = gateway or ''
                pid = pid or ''
                key = key or ''
                notify_url = notify_url or ''
                return_url = return_url or ''

        self.gateway = gateway.rstrip('/') if gateway else ''
        self.pid = pid
        self.key = key
        self.notify_url = notify_url
        self.return_url = return_url

    def is_configured(self):
        """Check if MaPay is properly configured"""
        return bool(self.gateway and self.pid and self.key)

    def _sign(self, params):
        """Generate MD5 signature (auto-filters empty params)"""
        filtered = {k: v for k, v in params.items() if v}
        sign_str = '&'.join([f"{k}={v}" for k, v in sorted(filtered.items())])
        return hashlib.md5((sign_str + self.key).encode()).hexdigest().lower()

    def create_order(self, amount, pay_type, out_trade_no, subject, param=''):
        """Create a MaPay order.

        Args:
            amount: Payment amount.
            pay_type: Payment method (alipay/wxpay/qqpay).
            out_trade_no: Merchant order number.
            subject: Product name.
            param: Custom parameter.

        Returns:
            dict: {'trade_no': ..., 'pay_url': ...} on success, {'error': ...} on failure.
        """
        if not self.is_configured():
            return {'error': '码支付未配置'}

        params = {
            'pid': self.pid,
            'type': pay_type,
            'out_trade_no': out_trade_no,
            'notify_url': self.notify_url,
            'return_url': self.return_url,
            'name': subject,
            'money': str(round(float(amount), 2)),
            'param': param,
        }
        params = {k: v for k, v in params.items() if v}
        params['sign'] = self._sign(params)
        params['sign_type'] = 'MD5'

        try:
            resp = requests.post(f"{self.gateway}/mapi.php", data=params, timeout=10).json()
            if resp.get('code') != 1:
                return {'error': resp.get('msg', '创建订单失败'), 'raw': resp}
            trade_no = resp.get('trade_no')
            pay_url = f"{self.gateway}/pay/{trade_no}"
            return {'trade_no': trade_no, 'pay_url': pay_url, 'raw': resp}
        except Exception as e:
            return {'error': str(e)}

    def check_order(self, out_trade_no):
        """Query MaPay order status.

        Args:
            out_trade_no: Merchant order number.

        Returns:
            dict: Raw response data.
        """
        if not self.is_configured():
            return {'error': '码支付未配置'}

        try:
            resp = requests.get(
                f"{self.gateway}/xpay/epay/api.php",
                params={
                    'act': 'order',
                    'pid': self.pid,
                    'key': self.key,
                    'out_trade_no': out_trade_no,
                },
                timeout=10
            ).json()
            return resp
        except Exception as e:
            return {'error': str(e)}

    def is_paid(self, out_trade_no):
        """Check if an order has been paid.

        Args:
            out_trade_no: Merchant order number.

        Returns:
            bool: Whether payment succeeded.
        """
        data = self.check_order(out_trade_no)
        return data.get('code') == 1 and data.get('status') == 1
