"""小程序资金冻结只读接口。

仅返回当前登录用户自己的冻结汇总/明细，不改余额、不触发解冻。
字段均为增量返回，旧前端忽略即可。
"""
from __future__ import annotations

from decimal import Decimal, ROUND_HALF_UP
from typing import Any, Dict, List

from django.core.exceptions import ObjectDoesNotExist
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework.views import APIView

from jituan.models import ClubFundFreezeConfig, FundFreezeLedger, FundUnfreezeEvent
from jituan.services.club_user import get_user_club_id
from jituan.services.fund_freeze import (
    ROLE_DASHOU,
    ROLE_GUANSHI,
    ROLE_SHENHEGUAN,
    ROLE_ZUZHANG,
)

ROLE_LABEL = {
    ROLE_DASHOU: '接单员',
    ROLE_GUANSHI: '管事',
    ROLE_ZUZHANG: '组长',
    ROLE_SHENHEGUAN: '考核官',
}

STATUS_LABEL = {
    FundFreezeLedger.STATUS_FROZEN: '冻结中',
    FundFreezeLedger.STATUS_PARTIAL: '部分解冻',
    FundFreezeLedger.STATUS_DONE: '已解冻',
    FundFreezeLedger.STATUS_VOID: '已作废',
}

SOURCE_LABEL = {
    'order_settle': '订单结算',
    'fenhong': '分红入账',
    'kaohe_fee': '考核费用',
}


def _money(v) -> str:
    try:
        return str(Decimal(str(v or 0)).quantize(Decimal('0.01'), rounding=ROUND_HALF_UP))
    except Exception:
        return '0.00'


def _profile_dongjie(user, attr: str) -> str:
    try:
        profile = getattr(user, attr)
        return _money(getattr(profile, 'dongjie_yue', 0))
    except (ObjectDoesNotExist, AttributeError):
        return '0.00'


def _profile_withdrawable(user, attr: str, field: str = 'yue') -> str:
    try:
        profile = getattr(user, attr)
        return _money(getattr(profile, field, 0))
    except (ObjectDoesNotExist, AttributeError):
        return '0.00'


def _default_freeze_reason() -> str:
    return (
        '部分佣金暂存为冻结保障金，用于订单售后与纠纷保障；'
        '按俱乐部规则到期或达标后自动转入可提现余额，冻结中金额不可提现。'
    )


def _freeze_display_reasons(club_id: str) -> Dict[str, str]:
    """按角色返回冻结说明；无配置时用统一默认文案。"""
    default = _default_freeze_reason()
    out = {
        ROLE_DASHOU: default,
        ROLE_GUANSHI: default,
        ROLE_ZUZHANG: default,
        ROLE_SHENHEGUAN: default,
    }
    if not club_id:
        return out
    try:
        for row in ClubFundFreezeConfig.query.filter(club_id=club_id):
            if row.role in out and (row.remark or '').strip():
                out[row.role] = row.remark.strip()
    except Exception:
        pass
    return out


class FundFreezeMineView(APIView):
    """
    POST /yonghu/fund-freeze-mine
    当前用户冻结汇总（可提现 + 冻结中，按角色）。
    """
    permission_classes = [IsAuthenticated]

    def post(self, request):
        user = request.user
        club_id = get_user_club_id(user) or ''
        roles: List[Dict[str, Any]] = [
            {
                'role': ROLE_DASHOU,
                'role_name': ROLE_LABEL[ROLE_DASHOU],
                'withdrawable': _profile_withdrawable(user, 'DashouProfile', 'yue'),
                'dongjie_yue': _profile_dongjie(user, 'DashouProfile'),
            },
            {
                'role': ROLE_GUANSHI,
                'role_name': ROLE_LABEL[ROLE_GUANSHI],
                'withdrawable': _profile_withdrawable(user, 'GuanshiProfile', 'yue'),
                'dongjie_yue': _profile_dongjie(user, 'GuanshiProfile'),
            },
            {
                'role': ROLE_ZUZHANG,
                'role_name': ROLE_LABEL[ROLE_ZUZHANG],
                'withdrawable': _profile_withdrawable(user, 'ZuzhangProfile', 'ketixian_jine'),
                'dongjie_yue': _profile_dongjie(user, 'ZuzhangProfile'),
            },
            {
                'role': ROLE_SHENHEGUAN,
                'role_name': ROLE_LABEL[ROLE_SHENHEGUAN],
                'withdrawable': _profile_withdrawable(user, 'ShenheguanProfile', 'yue'),
                'dongjie_yue': _profile_dongjie(user, 'ShenheguanProfile'),
            },
        ]
        # 只展示有身份余额或冻结的角色，避免空壳干扰
        visible = [
            r for r in roles
            if Decimal(r['withdrawable']) > 0 or Decimal(r['dongjie_yue']) > 0
        ]
        total_dongjie = sum((Decimal(r['dongjie_yue']) for r in roles), Decimal('0.00'))
        total_withdrawable = sum((Decimal(r['withdrawable']) for r in roles), Decimal('0.00'))

        reasons = _freeze_display_reasons(club_id)
        display_reason = reasons.get(ROLE_DASHOU) or _default_freeze_reason()

        return Response({
            'code': 200,
            'msg': '获取成功',
            'data': {
                'club_id': club_id,
                'roles': visible or roles[:1],
                'all_roles': roles,
                'total_dongjie': _money(total_dongjie),
                'total_withdrawable': _money(total_withdrawable),
                'has_freeze': total_dongjie > 0,
                'display_reason': display_reason,
                'freeze_display_reasons': reasons,
            },
        })


class FundFreezeMyLedgerView(APIView):
    """
    POST /yonghu/fund-freeze-ledger
    当前用户冻结明细（只读分页）。
    body: page, page_size, role?, status?
    """
    permission_classes = [IsAuthenticated]

    def post(self, request):
        user = request.user
        uid = user.UserUID
        club_id = get_user_club_id(user) or ''
        data = request.data if isinstance(request.data, dict) else {}
        page = max(1, int(data.get('page') or 1))
        page_size = min(50, max(1, int(data.get('page_size') or data.get('limit') or 20)))
        role = (data.get('role') or '').strip().lower()
        status = data.get('status')

        qs = FundFreezeLedger.query.filter(user_id=uid)
        if club_id:
            qs = qs.filter(club_id=club_id)
        if role:
            qs = qs.filter(role=role)
        if status not in (None, ''):
            try:
                qs = qs.filter(status=int(status))
            except (TypeError, ValueError):
                pass

        total = qs.count()
        rows = qs.order_by('-id')[(page - 1) * page_size: page * page_size]
        items = []
        for r in rows:
            remain = Decimal(str(r.amount_total or 0)) - Decimal(str(r.amount_unfrozen or 0))
            items.append({
                'id': r.id,
                'role': r.role,
                'role_name': ROLE_LABEL.get(r.role, r.role),
                'amount_total': _money(r.amount_total),
                'amount_unfrozen': _money(r.amount_unfrozen),
                'amount_remain': _money(remain),
                'status': r.status,
                'status_label': STATUS_LABEL.get(r.status, str(r.status)),
                'frozen_at': r.frozen_at.strftime('%Y-%m-%d %H:%M') if r.frozen_at else '',
                'next_eligible_at': (
                    r.next_eligible_at.strftime('%Y-%m-%d %H:%M') if r.next_eligible_at else ''
                ),
                'source_type': r.source_type,
                'source_label': SOURCE_LABEL.get(r.source_type, r.source_type or '入账'),
                'order_id': r.order_id or '',
                'freeze_reason': r.freeze_reason or (
                    (r.config_snapshot or {}).get('display_reason')
                    or (r.config_snapshot or {}).get('remark')
                    or ''
                ),
                'current_step': r.current_step,
            })

        return Response({
            'code': 200,
            'msg': '获取成功',
            'data': {
                'club_id': club_id,
                'list': items,
                'total': total,
                'page': page,
                'page_size': page_size,
                'has_more': page * page_size < total,
            },
        })


class FundFreezeMyLedgerDetailView(APIView):
    """
    POST /yonghu/fund-freeze-ledger-detail
    单笔冻结单 + 解冻事件（仅本人）。
    body: ledger_id
    """
    permission_classes = [IsAuthenticated]

    def post(self, request):
        user = request.user
        data = request.data if isinstance(request.data, dict) else {}
        try:
            ledger_id = int(data.get('ledger_id') or data.get('id') or 0)
        except (TypeError, ValueError):
            return Response({'code': 400, 'msg': 'ledger_id 无效', 'data': None}, status=400)
        if ledger_id <= 0:
            return Response({'code': 400, 'msg': '缺少 ledger_id', 'data': None}, status=400)

        ledger = FundFreezeLedger.query.filter(id=ledger_id, user_id=user.UserUID).first()
        if not ledger:
            return Response({'code': 404, 'msg': '记录不存在', 'data': None}, status=404)

        remain = Decimal(str(ledger.amount_total or 0)) - Decimal(str(ledger.amount_unfrozen or 0))
        events = FundUnfreezeEvent.query.filter(
            ledger_id=ledger.id,
        ).order_by('step_seq', 'id')[:50]
        event_list = [{
            'id': e.id,
            'step_seq': e.step_seq,
            'amount': _money(e.amount),
            'unfrozen_at': e.unfrozen_at.strftime('%Y-%m-%d %H:%M') if e.unfrozen_at else '',
            'trigger': e.trigger,
            'reason': e.reason or '',
        } for e in events]

        return Response({
            'code': 200,
            'msg': '获取成功',
            'data': {
                'id': ledger.id,
                'role': ledger.role,
                'role_name': ROLE_LABEL.get(ledger.role, ledger.role),
                'amount_total': _money(ledger.amount_total),
                'amount_unfrozen': _money(ledger.amount_unfrozen),
                'amount_remain': _money(remain),
                'status': ledger.status,
                'status_label': STATUS_LABEL.get(ledger.status, str(ledger.status)),
                'frozen_at': ledger.frozen_at.strftime('%Y-%m-%d %H:%M') if ledger.frozen_at else '',
                'next_eligible_at': (
                    ledger.next_eligible_at.strftime('%Y-%m-%d %H:%M')
                    if ledger.next_eligible_at else ''
                ),
                'source_type': ledger.source_type,
                'source_label': SOURCE_LABEL.get(ledger.source_type, ledger.source_type or '入账'),
                'order_id': ledger.order_id or '',
                'freeze_reason': ledger.freeze_reason or (
                    (ledger.config_snapshot or {}).get('display_reason')
                    or (ledger.config_snapshot or {}).get('remark')
                    or ''
                ),
                'current_step': ledger.current_step,
                'events': event_list,
            },
        })
