"""投诉工单 API：用户提交/列表/升级 + 图片上传 + 客服处理。"""
import logging
import uuid

from django.utils import timezone
from rest_framework.parsers import FormParser, JSONParser, MultiPartParser
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework import status

from gongdan.constants import (
    MAX_IMAGES, OSS_PREFIX, PERM_VIEW, PERM_HANDLE, TYPE_LABELS, STATUS_LABELS,
)
from gongdan.models import Gongdan
from gongdan.services import (
    GongdanError,
    create_gongdan,
    escalate_gongdan,
    handle_gongdan,
    serialize_gongdan,
    user_mark_dissatisfied,
)
from utils.oss_utils import upload_to_oss, validate_image

logger = logging.getLogger(__name__)


def _ok(data=None, message='ok', code=200):
    body = {'code': code, 'message': message, 'msg': message}
    if data is not None:
        body['data'] = data
    return Response(body, status=status.HTTP_200_OK)


def _err(message, http=400, code=None):
    c = code if code is not None else http
    return Response(
        {'code': c, 'message': message, 'msg': message},
        status=http,
    )


def _resolve_club(request):
    try:
        from jituan.services.club_write import resolve_club_id_for_write
        return resolve_club_id_for_write(request, request.user)
    except Exception:
        return getattr(request.user, 'club_id', None) or None


class GongdanUploadImageView(APIView):
    """上传证据图，返回 URL。路径：POST /gongdan/upload-image/"""
    permission_classes = [IsAuthenticated]
    parser_classes = (MultiPartParser, FormParser)

    def post(self, request):
        f = request.FILES.get('file') or request.FILES.get('image') or request.FILES.get('tupian')
        if not f:
            return _err('请选择图片')
        ok, msg = validate_image(f)
        if not ok:
            return _err(msg)
        ext = (f.name.rsplit('.', 1)[-1] if '.' in f.name else 'jpg').lower()
        if ext not in ('jpg', 'jpeg', 'png', 'gif', 'webp', 'bmp'):
            ext = 'jpg'
        uid = getattr(request.user, 'UserUID', 'anon')
        day = timezone.now().strftime('%Y%m%d')
        path = f'{OSS_PREFIX}/{day}/{uid}/{uuid.uuid4().hex}.{ext}'
        url = upload_to_oss(f, path)
        if not url:
            return _err('上传失败，请稍后重试', http=500)
        return _ok({'url': url}, '上传成功')


class GongdanCreateView(APIView):
    """创建投诉工单。POST /gongdan/create/"""
    permission_classes = [IsAuthenticated]
    parser_classes = (JSONParser, FormParser, MultiPartParser)

    def post(self, request):
        d = request.data
        images = d.get('images') or d.get('image_urls') or []
        if isinstance(images, str):
            images = [x.strip() for x in images.split(',') if x.strip()]
        try:
            gd = create_gongdan(
                yonghuid=request.user.UserUID,
                leixing=d.get('leixing'),
                shuoming=d.get('shuoming') or d.get('content') or '',
                club_id=_resolve_club(request),
                order_id=d.get('order_id') or d.get('OrderID'),
                chongzhi_id=d.get('chongzhi_id') or d.get('dingdanid') or d.get('dingdan_id'),
                fadan_id=d.get('fadan_id') or d.get('penalty_id'),
                guanshi_id=d.get('guanshi_id'),
                image_urls=images,
            )
            return _ok(serialize_gongdan(gd, include_images=True, include_shengji=True), '提交成功')
        except GongdanError as e:
            return _err(str(e))
        except Exception as e:
            logger.error('创建工单失败: %s', e, exc_info=True)
            return _err('提交失败，请稍后重试', http=500)


class GongdanMyListView(APIView):
    """我的投诉列表。POST/GET /gongdan/my-list/"""
    permission_classes = [IsAuthenticated]

    def get(self, request):
        return self._list(request)

    def post(self, request):
        return self._list(request)

    def _list(self, request):
        page = int(request.data.get('page') or request.query_params.get('page') or 1)
        page_size = min(int(request.data.get('page_size') or request.query_params.get('page_size') or 20), 50)
        qs = Gongdan.query.filter(shenqingren_id=request.user.UserUID).order_by('-CreateTime')
        total = qs.count()
        start = max(page - 1, 0) * page_size
        rows = qs[start:start + page_size]
        return _ok({
            'list': [serialize_gongdan(g, include_images=False) for g in rows],
            'total': total,
            'page': page,
            'page_size': page_size,
        })


class GongdanDetailView(APIView):
    """工单详情。POST /gongdan/detail/  {gongdan_id}"""
    permission_classes = [IsAuthenticated]

    def post(self, request):
        gid = (request.data.get('gongdan_id') or '').strip()
        if not gid:
            return _err('工单号不能为空')
        gd = Gongdan.query.filter(gongdan_id=gid).first()
        if not gd:
            return _err('工单不存在', http=404)
        # 申请人或有客服查看权限
        if gd.shenqingren_id != request.user.UserUID:
            from backend.utils import verify_kefu_permission
            from gongdan.constants import PERM_VIEW, PERM_HANDLE
            kefu, perms_or_resp = verify_kefu_permission(
                request, request.data.get('username') or getattr(request.user, 'Phone', None),
            )
            if not kefu:
                return perms_or_resp
            perms = perms_or_resp if isinstance(perms_or_resp, list) else []
            if PERM_VIEW not in perms and PERM_HANDLE not in perms and '000001' not in perms:
                # 超管占位：is admin via kefu object
                is_admin = getattr(request.user, 'UserType', '') == 'admin' or getattr(request.user, 'IsSuperuser', False)
                if not is_admin:
                    return _err('无权查看', http=403)
        return _ok(serialize_gongdan(gd, include_images=True, include_shengji=True))


class GongdanEscalateView(APIView):
    """继续投诉/升级。POST /gongdan/escalate/"""
    permission_classes = [IsAuthenticated]

    def post(self, request):
        d = request.data
        images = d.get('images')
        if images is not None and isinstance(images, str):
            images = [x.strip() for x in images.split(',') if x.strip()]
        try:
            gd = escalate_gongdan(
                gongdan_id=(d.get('gongdan_id') or '').strip(),
                yonghuid=request.user.UserUID,
                shuoming=d.get('shuoming') or '',
                image_urls=images,
            )
            return _ok(serialize_gongdan(gd, include_images=True, include_shengji=True), '已提交补充投诉')
        except GongdanError as e:
            return _err(str(e))
        except Exception as e:
            logger.error('升级工单失败: %s', e, exc_info=True)
            return _err('提交失败', http=500)


class GongdanDissatisfiedView(APIView):
    """标记不满意。POST /gongdan/dissatisfied/"""
    permission_classes = [IsAuthenticated]

    def post(self, request):
        try:
            gd = user_mark_dissatisfied(
                gongdan_id=(request.data.get('gongdan_id') or '').strip(),
                yonghuid=request.user.UserUID,
            )
            return _ok(serialize_gongdan(gd), '已标记不满意，可继续投诉')
        except GongdanError as e:
            return _err(str(e))


class GongdanMetaView(APIView):
    """类型/状态枚举，供前端展示。GET /gongdan/meta/"""
    permission_classes = [IsAuthenticated]

    def get(self, request):
        return _ok({
            'types': [{'value': k, 'label': v} for k, v in TYPE_LABELS.items()],
            'statuses': [{'value': k, 'label': v} for k, v in STATUS_LABELS.items()],
            'max_images': MAX_IMAGES,
        })


class ChongzhiRecordListView(APIView):
    """当前用户充值记录（Czjilu），供投诉选 ID / 充值记录页。POST /gongdan/chongzhi-list/"""
    permission_classes = [IsAuthenticated]

    def post(self, request):
        from products.models import Czjilu
        from products.czjilu_types import (
            CZJILU_LEIXING_HUIYUAN, CZJILU_LEIXING_YAJIN, CZJILU_LEIXING_JIFEN,
            CZJILU_LEIXING_SHANGJIA,
        )
        page = int(request.data.get('page') or 1)
        page_size = min(int(request.data.get('page_size') or 20), 50)
        qs = Czjilu.query.filter(yonghuid=request.user.UserUID).order_by('-CreateTime')
        leixing = request.data.get('leixing')
        if leixing not in (None, ''):
            qs = qs.filter(leixing=int(leixing))
        total = qs.count()
        start = max(page - 1, 0) * page_size
        type_map = {
            CZJILU_LEIXING_HUIYUAN: '会员',
            CZJILU_LEIXING_YAJIN: '押金',
            CZJILU_LEIXING_JIFEN: '积分',
            CZJILU_LEIXING_SHANGJIA: '商家充值',
            5: '考核',
            6: '罚款',
        }
        status_map = {9: '待支付', 3: '已支付', 2: '已取消', 8: '履约失败', 10: '业务失败'}
        rows = []
        for o in qs[start:start + page_size]:
            rows.append({
                'dingdan_id': o.dingdan_id,
                'leixing': o.leixing,
                'leixing_label': type_map.get(o.leixing, str(o.leixing)),
                'jine': str(o.jine),
                'zhuangtai': o.zhuangtai,
                'zhuangtai_label': status_map.get(o.zhuangtai, str(o.zhuangtai)),
                'shuoming': o.shuoming or '',
                'CreateTime': o.CreateTime.isoformat() if getattr(o, 'CreateTime', None) else '',
            })
        return _ok({'list': rows, 'total': total, 'page': page, 'page_size': page_size})


# ---------- 客服后台 ----------

def _require_kefu_perm(request, *need_codes):
    from backend.utils import verify_kefu_permission
    username = request.data.get('username') or request.query_params.get('username') or getattr(request.user, 'Phone', None)
    kefu, perms_or_resp = verify_kefu_permission(request, username)
    if not kefu:
        return None, None, perms_or_resp
    perms = perms_or_resp if isinstance(perms_or_resp, list) else []
    is_admin = (
        getattr(request.user, 'UserType', '') == 'admin'
        or getattr(request.user, 'IsSuperuser', False)
        or '000001' in perms
    )
    if is_admin:
        return kefu, perms, None
    if not any(c in perms for c in need_codes):
        return None, None, _err('无工单权限', http=403)
    return kefu, perms, None


class GongdanAdminListView(APIView):
    """客服工单列表。POST /gongdan/admin/list/"""
    permission_classes = [IsAuthenticated]

    def post(self, request):
        kefu, perms, err = _require_kefu_perm(request, PERM_VIEW, PERM_HANDLE)
        if err:
            return err
        page = int(request.data.get('page') or 1)
        page_size = min(int(request.data.get('page_size') or 20), 100)
        from django.db.models import Q
        qs = Gongdan.query.all().order_by('-CreateTime')
        try:
            from jituan.services.club_context import filter_club_char_field
            qs = filter_club_char_field(qs, request, field='club_id')
        except Exception:
            pass
        zhuangtai = request.data.get('zhuangtai')
        leixing = request.data.get('leixing')
        keyword = (request.data.get('keyword') or '').strip()
        only_escalated = str(request.data.get('only_escalated') or '').lower() in ('1', 'true', 'yes')
        need_handle = str(request.data.get('need_handle') or '').lower() in ('1', 'true', 'yes')
        if need_handle:
            qs = qs.filter(Q(zhuangtai=1) | Q(zhuangtai=3))
        elif zhuangtai not in (None, ''):
            qs = qs.filter(zhuangtai=int(zhuangtai))
        if only_escalated:
            qs = qs.filter(shengji_cishu__gt=0).filter(Q(zhuangtai=1) | Q(zhuangtai=3))
        if leixing not in (None, ''):
            qs = qs.filter(leixing=int(leixing))
        if keyword:
            qs = qs.filter(
                Q(gongdan_id__icontains=keyword)
                | Q(shenqingren_id__icontains=keyword)
                | Q(order_id__icontains=keyword)
                | Q(chongzhi_id__icontains=keyword)
                | Q(fadan_id__icontains=keyword)
            )
        total = qs.count()
        start = max(page - 1, 0) * page_size
        rows = [serialize_gongdan(g, include_images=False) for g in qs[start:start + page_size]]

        # 统计基于俱乐部范围全量（不受当前筛选影响），方便客服一眼看到待办量
        stats_qs = Gongdan.query.all()
        try:
            from jituan.services.club_context import filter_club_char_field
            stats_qs = filter_club_char_field(stats_qs, request, field='club_id')
        except Exception:
            pass
        stats = {
            'total': stats_qs.count(),
            'pending': stats_qs.filter(zhuangtai=1).count(),
            'done': stats_qs.filter(zhuangtai=2).count(),
            'dissatisfied': stats_qs.filter(zhuangtai=3).count(),
            'closed': stats_qs.filter(zhuangtai=4).count(),
            'escalated': stats_qs.filter(shengji_cishu__gt=0).filter(
                Q(zhuangtai=1) | Q(zhuangtai=3)
            ).count(),
            'need_handle': stats_qs.filter(Q(zhuangtai=1) | Q(zhuangtai=3)).count(),
        }
        return _ok({
            'list': rows,
            'total': total,
            'page': page,
            'page_size': page_size,
            'stats': stats,
        })


class GongdanAdminHandleView(APIView):
    """客服处理工单。POST /gongdan/admin/handle/"""
    permission_classes = [IsAuthenticated]

    def post(self, request):
        kefu, perms, err = _require_kefu_perm(request, PERM_HANDLE)
        if err:
            return err
        d = request.data
        handler_uid = getattr(request.user, 'UserUID', '') or getattr(request.user, 'Phone', '')
        handler_name = getattr(request.user, 'NickName', None) or getattr(request.user, 'Phone', '') or handler_uid
        try:
            gd = handle_gongdan(
                gongdan_id=(d.get('gongdan_id') or '').strip(),
                handler_uid=handler_uid,
                handler_name=handler_name,
                action=d.get('action') or 'done',
                chuli_jieguo=d.get('chuli_jieguo') or d.get('jieguo') or '',
            )
            return _ok(serialize_gongdan(gd, include_images=True, include_shengji=True), '处理成功')
        except GongdanError as e:
            return _err(str(e))
        except Exception as e:
            logger.error('处理工单失败: %s', e, exc_info=True)
            return _err('处理失败', http=500)
