"""俱乐部支付通道后台管理（付呗配置 CRUD + 选用 wechat/fubei）。"""
from __future__ import annotations

import logging

from rest_framework.parsers import JSONParser
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework.views import APIView

from backend.utils import verify_kefu_permission
from jituan.constants import (
    CLUB_ID_DEFAULT,
    MINI_PAY_CHANNEL_FUBEI,
    MINI_PAY_CHANNEL_WECHAT,
    PAY_CHANNEL_FUBEI_WX_MINI,
)
from jituan.models import Club, ClubPaymentChannel
from jituan.services.club_payment_channel import (
    encrypt_secret_field,
    invalidate_club_payment_cache,
)
from jituan.services.mini_pay_router import get_club_mini_pay_channel, set_club_mini_pay_channel
from jituan.services.admin_context import can_manage_admin_assignments

logger = logging.getLogger(__name__)


def _mask_secret(plain: str) -> str:
    s = (plain or '').strip()
    if not s:
        return ''
    if len(s) <= 8:
        return '****'
    return s[:4] + '****' + s[-4:]


def _serialize_channel(row: ClubPaymentChannel, reveal_secret: bool = False) -> dict:
    from jituan.services.club_payment_channel import decrypt_secret_field
    secret = decrypt_secret_field(row.api_key_enc) if row.api_key_enc else ''
    extra = dict(row.extra_json or {})
    return {
        'id': row.id,
        'club_id': row.club_id,
        'channel': row.channel,
        'name': row.name,
        'enabled': row.enabled,
        'is_default': row.is_default,
        'sort_order': row.sort_order,
        'sandbox': row.sandbox,
        'app_id': row.app_id,
        'mch_id': row.mch_id,
        'mini_app_id': row.mini_app_id,
        'store_id': extra.get('store_id') or extra.get('fubei_store_id') or '',
        'merchant_id': extra.get('merchant_id') or row.mch_id or '',
        'api_key_masked': _mask_secret(secret),
        'api_key': secret if reveal_secret else '',
        'api_key_configured': bool(secret),
        'notify_url': row.notify_url,
        'gateway_url': row.gateway_url,
        'remark': row.remark,
        'extra_json': extra,
    }


class ClubPaymentChannelManageView(APIView):
    """POST /jituan/houtai/payment-channel-manage

    actions:
      - get: 当前俱乐部 mini_pay_channel + 付呗通道列表
      - set_mini_pay_channel: {mini_pay_channel: wechat|fubei}
      - save_fubei: 新增或更新付呗配置（按 id 或 name）
      - set_default / enable / disable
      - delete
    """
    permission_classes = [IsAuthenticated]
    parser_classes = [JSONParser]

    def post(self, request):
        try:
            username = (request.data.get('phone') or request.data.get('username') or '').strip()
            if not username:
                return Response({'code': 401, 'msg': '缺少账号'}, status=401)
            kefu_obj, permissions = verify_kefu_permission(request, username)
            if kefu_obj is None:
                return permissions
            if not can_manage_admin_assignments(request.user):
                return Response({'code': 403, 'msg': '仅集团超管可管理支付通道'}, status=403)

            action = (request.data.get('action') or 'get').strip()
            club_id = (request.data.get('club_id') or '').strip() or CLUB_ID_DEFAULT
            club = Club.query.filter(club_id=club_id).first()
            if not club:
                return Response({'code': 1, 'msg': f'俱乐部 {club_id} 不存在'})

            if action == 'get':
                rows = ClubPaymentChannel.query.filter(
                    club_id=club_id, channel=PAY_CHANNEL_FUBEI_WX_MINI,
                ).order_by('-is_default', 'sort_order', 'id')
                return Response({
                    'code': 0,
                    'data': {
                        'club_id': club_id,
                        'mini_pay_channel': get_club_mini_pay_channel(club_id),
                        'fubei_channels': [_serialize_channel(r) for r in rows],
                    },
                })

            if action == 'set_mini_pay_channel':
                ch = (request.data.get('mini_pay_channel') or '').strip().lower()
                try:
                    set_club_mini_pay_channel(club_id, ch)
                except ValueError as exc:
                    return Response({'code': 400, 'msg': str(exc)})
                if ch == MINI_PAY_CHANNEL_FUBEI:
                    fb = ClubPaymentChannel.query.filter(
                        club_id=club_id, channel=PAY_CHANNEL_FUBEI_WX_MINI, enabled=1,
                    ).first()
                    if not fb:
                        return Response({
                            'code': 0,
                            'msg': '已切换为付呗，但尚未配置付呗通道，请先保存付呗配置',
                            'data': {'mini_pay_channel': ch},
                            'warning': True,
                        })
                return Response({
                    'code': 0,
                    'msg': '已切换小程序收款通道',
                    'data': {'mini_pay_channel': ch},
                })

            if action == 'save_fubei':
                return self._save_fubei(request, club_id)

            if action in ('enable', 'disable', 'set_default', 'delete'):
                row_id = request.data.get('id')
                row = ClubPaymentChannel.query.filter(
                    id=row_id, club_id=club_id, channel=PAY_CHANNEL_FUBEI_WX_MINI,
                ).first()
                if not row:
                    return Response({'code': 1, 'msg': '配置不存在'})
                if action == 'delete':
                    row.delete()
                    invalidate_club_payment_cache(club_id, PAY_CHANNEL_FUBEI_WX_MINI)
                    return Response({'code': 0, 'msg': '已删除'})
                if action == 'enable':
                    row.enabled = 1
                    row.save(update_fields=['enabled'])
                elif action == 'disable':
                    row.enabled = 0
                    row.save(update_fields=['enabled'])
                elif action == 'set_default':
                    ClubPaymentChannel.objects.filter(
                        club_id=club_id, channel=PAY_CHANNEL_FUBEI_WX_MINI, is_default=True,
                    ).exclude(id=row.id).update(is_default=False)
                    row.is_default = True
                    row.enabled = 1
                    row.save(update_fields=['is_default', 'enabled'])
                invalidate_club_payment_cache(club_id, PAY_CHANNEL_FUBEI_WX_MINI)
                return Response({'code': 0, 'msg': 'ok', 'data': _serialize_channel(row)})

            return Response({'code': 400, 'msg': f'未知 action: {action}'})
        except Exception as exc:
            logger.error('payment-channel-manage 异常: %s', exc, exc_info=True)
            return Response({'code': 500, 'msg': str(exc)})

    def _save_fubei(self, request, club_id: str):
        name = (request.data.get('name') or '主付呗').strip() or '主付呗'
        row_id = request.data.get('id')
        app_id = (request.data.get('app_id') or '').strip()
        api_key = request.data.get('api_key')
        store_id = request.data.get('store_id')
        merchant_id = (request.data.get('merchant_id') or request.data.get('mch_id') or '').strip()
        mini_app_id = (request.data.get('mini_app_id') or '').strip()
        remark = (request.data.get('remark') or '').strip()

        if not app_id:
            return Response({'code': 400, 'msg': '请填写付呗开放平台 app_id'})
        if store_id in (None, ''):
            return Response({'code': 400, 'msg': '请填写门店 store_id'})

        row = None
        if row_id:
            row = ClubPaymentChannel.query.filter(
                id=row_id, club_id=club_id, channel=PAY_CHANNEL_FUBEI_WX_MINI,
            ).first()
        if not row:
            row = ClubPaymentChannel.query.filter(
                club_id=club_id, channel=PAY_CHANNEL_FUBEI_WX_MINI, name=name,
            ).first()
        creating = row is None
        if creating:
            row = ClubPaymentChannel(
                club_id=club_id,
                channel=PAY_CHANNEL_FUBEI_WX_MINI,
                name=name,
                enabled=1,
                is_default=True,
            )

        row.app_id = app_id
        row.mch_id = merchant_id
        row.mini_app_id = mini_app_id
        row.remark = remark
        if api_key is not None and str(api_key).strip():
            row.api_key_enc = encrypt_secret_field(str(api_key).strip())
        elif creating:
            return Response({'code': 400, 'msg': '新建付呗配置必须填写接口密钥'})

        extra = dict(row.extra_json or {})
        try:
            extra['store_id'] = int(store_id)
        except (TypeError, ValueError):
            return Response({'code': 400, 'msg': 'store_id 必须是数字'})
        if merchant_id:
            extra['merchant_id'] = merchant_id
        row.extra_json = extra

        # 设为默认时取消同通道其它默认
        if request.data.get('is_default', True):
            ClubPaymentChannel.objects.filter(
                club_id=club_id, channel=PAY_CHANNEL_FUBEI_WX_MINI, is_default=True,
            ).exclude(id=getattr(row, 'id', None) or 0).update(is_default=False)
            row.is_default = True
            row.enabled = 1

        row.save()
        invalidate_club_payment_cache(club_id, PAY_CHANNEL_FUBEI_WX_MINI)

        # 可选：保存后同时切到付呗
        if request.data.get('activate'):
            set_club_mini_pay_channel(club_id, MINI_PAY_CHANNEL_FUBEI)

        return Response({
            'code': 0,
            'msg': '付呗配置已保存',
            'data': {
                'channel': _serialize_channel(row),
                'mini_pay_channel': get_club_mini_pay_channel(club_id),
            },
        })
