"""模块：支付 SAAS 数据模型
SAAS 级支付配置与交易流水——不绑定具体业务。
子服务自行关联 payment_transaction_id 到自己的订单。"""

import uuid
import datetime
from django.db import models
from gvsdsdk.model_base import QModel
from gvsdsdk.models import UUIDField


class PaymentGatewayConfig(QModel):
    """支付网关配置表——每个租户每个渠道一条配置

    存储加密后的支付密钥，子服务通过此表配置自己的支付能力。
    SAAS 主服务器不关心具体业务，只提供通道。
    """

    ConfigUUID = UUIDField(primary_key=True)
    TenantUUID = UUIDField()
    Platform = models.CharField(max_length=32)
    AppID = models.CharField(max_length=64, default='')
    MchID = models.CharField(max_length=64, default='')
    APIKeyEncrypted = models.CharField(max_length=512, default='')
    PrivateKeyEncrypted = models.TextField(default='')
    PublicKeyEncrypted = models.TextField(default='')
    CertPath = models.CharField(max_length=512, default='')
    CertKeyPath = models.CharField(max_length=512, default='')
    NotifyURL = models.CharField(max_length=512, default='')
    ReturnURL = models.CharField(max_length=512, default='')
    ConfigExtra = models.JSONField(default=dict)
    ConfigStatus = models.SmallIntegerField(default=1)
    ConfigDefault = models.BooleanField(default=False)
    CreateTime = models.DateTimeField(default=datetime.datetime.utcnow)
    UpdateTime = models.DateTimeField(null=True, blank=True)

    class Meta:
        db_table = 'PaymentGatewayConfig'
        app_label = 'gvsdsdk'
        verbose_name = '支付网关配置'
        verbose_name_plural = '支付网关配置'
        unique_together = [('TenantUUID', 'Platform')]
        managed = False
        indexes = [
            models.Index(fields=['TenantUUID'], name='idx_paycfg_tenant'),
            models.Index(fields=['Platform'], name='idx_paycfg_platform'),
        ]

    def __str__(self):
        return f'{self.Platform}@{self.TenantUUID}'

    @property
    def IsActive(self):
        return self.ConfigStatus == 1

    def DecryptAPIKey(self):
        if not self.APIKeyEncrypted:
            return ''
        return _decrypt_field(self.APIKeyEncrypted)

    def DecryptPrivateKey(self):
        if not self.PrivateKeyEncrypted:
            return ''
        return _decrypt_field(self.PrivateKeyEncrypted)

    def DecryptPublicKey(self):
        if not self.PublicKeyEncrypted:
            return ''
        return _decrypt_field(self.PublicKeyEncrypted)

    @classmethod
    def FromTenantAndPlatform(cls, tenant_uuid, platform):
        try:
            return cls.objects.get(TenantUUID=tenant_uuid, Platform=platform, ConfigStatus=1)
        except cls.DoesNotExist:
            return None


class PaymentTransaction(QModel):
    """支付交易流水表——SAAS 级统一交易记录

    每笔支付/退款/转账操作都在此记录一条流水。
    子服务通过此表的 TransactionUUID 关联自己的业务订单。
    """

    TX_PAY = 'pay'
    TX_REFUND = 'refund'
    TX_TRANSFER = 'transfer'

    TX_TYPE_CHOICES = [
        (TX_PAY, '支付'),
        (TX_REFUND, '退款'),
        (TX_TRANSFER, '转账'),
    ]

    TX_PENDING = 0
    TX_SUCCESS = 1
    TX_FAILED = 2
    TX_CLOSED = 3

    TX_STATUS_CHOICES = [
        (TX_PENDING, '处理中'),
        (TX_SUCCESS, '成功'),
        (TX_FAILED, '失败'),
        (TX_CLOSED, '已关闭'),
    ]

    TransactionUUID = UUIDField(primary_key=True)
    TenantUUID = UUIDField()
    Platform = models.CharField(max_length=32)
    TransactionType = models.CharField(max_length=16, choices=TX_TYPE_CHOICES)
    OutTradeNO = models.CharField(max_length=64, unique=True)
    OutRefundNO = models.CharField(max_length=64, default='')
    ChannelTransactionID = models.CharField(max_length=128, default='')
    TotalAmount = models.DecimalField(max_digits=18, decimal_places=4, default=0)
    Currency = models.CharField(max_length=10, default='CNY')
    TransactionStatus = models.SmallIntegerField(
        default=TX_PENDING, choices=TX_STATUS_CHOICES,
    )
    Subject = models.CharField(max_length=256, default='')
    RawRequest = models.JSONField(default=dict)
    RawResponse = models.JSONField(default=dict)
    NotifyData = models.JSONField(default=dict)
    PayTime = models.DateTimeField(null=True, blank=True)
    CreateTime = models.DateTimeField(default=datetime.datetime.utcnow)
    UpdateTime = models.DateTimeField(null=True, blank=True)

    class Meta:
        db_table = 'PaymentTransaction'
        app_label = 'gvsdsdk'
        verbose_name = '支付交易流水'
        verbose_name_plural = '支付交易流水'
        ordering = ['-CreateTime']
        managed = False
        indexes = [
            models.Index(fields=['TenantUUID', 'CreateTime'], name='idx_paytx_tenant_time'),
            models.Index(fields=['Platform', 'TransactionStatus'], name='idx_paytx_platform_status'),
            models.Index(fields=['OutTradeNO'], name='idx_paytx_out_trade_no'),
        ]

    def __str__(self):
        return self.OutTradeNO

    @property
    def IsSuccess(self):
        return self.TransactionStatus == self.TX_SUCCESS

    def MarkSuccess(self, channel_transaction_id='', pay_time=None, notify_data=None):
        self.TransactionStatus = self.TX_SUCCESS
        self.ChannelTransactionID = channel_transaction_id
        self.PayTime = pay_time or datetime.datetime.utcnow()
        if notify_data:
            self.NotifyData = notify_data
        self.UpdateTime = datetime.datetime.utcnow()
        self.save(update_fields=[
            'TransactionStatus', 'ChannelTransactionID',
            'PayTime', 'NotifyData', 'UpdateTime',
        ])

    def MarkFailed(self, raw_response=None):
        self.TransactionStatus = self.TX_FAILED
        if raw_response:
            self.RawResponse = raw_response
        self.UpdateTime = datetime.datetime.utcnow()
        self.save(update_fields=['TransactionStatus', 'RawResponse', 'UpdateTime'])

    def MarkClosed(self):
        self.TransactionStatus = self.TX_CLOSED
        self.UpdateTime = datetime.datetime.utcnow()
        self.save(update_fields=['TransactionStatus', 'UpdateTime'])


def _decrypt_field(encrypted_value):
    import base64
    from django.conf import settings
    key = getattr(settings, 'PAYMENT_ENCRYPTION_KEY', 'SMANAGE-payment-default-key-32b')
    try:
        raw = base64.b64decode(encrypted_value)
        return bytes(a ^ b for a, b in zip(raw, key.encode() * (len(raw) // len(key.encode()) + 1))).decode('utf-8')
    except Exception:
        return encrypted_value


def EncryptField(plain_value):
    import base64
    from django.conf import settings
    if not plain_value:
        return ''
    key = getattr(settings, 'PAYMENT_ENCRYPTION_KEY', 'SMANAGE-payment-default-key-32b')
    raw = bytes(a ^ b for a, b in zip(
        plain_value.encode('utf-8'),
        key.encode() * (len(plain_value.encode('utf-8')) // len(key.encode()) + 1),
    ))
    return base64.b64encode(raw).decode('utf-8')
