"""小程序图标与频道 — 后台管理 API。"""
import os

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 backend.utils import verify_kefu_permission
from config.models import ClubMiniappIcon, ClubPindao, ClubPindaoImage
from jituan.services.club_context import resolve_effective_club_id
from jituan.services.display_config import forbid_display_write_in_all_scope, list_response_meta
from jituan.services.miniapp_assets import (
    ICON_FOLDER,
    CONFIG_ONLY_DELIVERY_KEYS,
    MINIAPP_ICON_LABELS,
    MINIAPP_ICON_META,
    POSTER_FOLDER,
    POSTER_ICON_KEYS,
    default_icon_path,
    get_miniapp_icons_dict,
    get_pindao_payload,
    get_poster_payload,
)
from products.views import delete_from_oss, upload_to_oss, validate_image

POPUP_PERM = '8080a'
PINDAO_FOLDER = 'beijing/pindao'


class ClubMiniappIconListView(APIView):
    """POST /jituan/houtai/miniapp-icon-list"""
    permission_classes = [IsAuthenticated]
    parser_classes = [JSONParser]

    def post(self, request):
        phone = (request.data.get('phone') or request.data.get('username') or '').strip()
        if not phone:
            return Response({'code': 401, 'msg': '缺少客服账号'})
        kefu, permissions = verify_kefu_permission(request, phone)
        if kefu is None:
            return permissions
        if POPUP_PERM not in permissions:
            return Response({'code': 403, 'msg': '无权限管理小程序图标'})

        club_id = resolve_effective_club_id(request, request.user)
        icons_db = {
            r.icon_key: r for r in ClubMiniappIcon.query.filter(club_id=club_id)
        }
        items = []
        for key, label in MINIAPP_ICON_META:
            row = icons_db.get(key)
            uploaded = bool(row and row.is_uploaded and (row.image_path or '').strip())
            if uploaded:
                image_path = row.image_path.strip()
            elif key in CONFIG_ONLY_DELIVERY_KEYS:
                # 未上传的大背景不回默认路径，避免后台预览 404、误以为已配置
                image_path = ''
            else:
                image_path = (row.image_path if row else '') or default_icon_path(key)
            items.append({
                'icon_key': key,
                'label': label,
                'image_path': image_path,
                'description': (row.description if row else '') or '',
                'is_active': row.is_active if row else True,
                'is_uploaded': uploaded,
                'id': row.id if row else None,
            })
        return Response({
            'code': 0,
            'data': {
                'icons': items,
                'folder': ICON_FOLDER,
                **list_response_meta(request),
            },
        })


class ClubMiniappIconManageView(APIView):
    """POST /jituan/houtai/miniapp-icon-manage action=upload|save_meta"""
    permission_classes = [IsAuthenticated]
    parser_classes = [MultiPartParser, FormParser, JSONParser]

    def post(self, request):
        phone = (request.data.get('phone') or request.data.get('username') or '').strip()
        if not phone:
            return Response({'code': 401, 'msg': '缺少客服账号'})
        kefu, permissions = verify_kefu_permission(request, phone)
        if kefu is None:
            return permissions
        if POPUP_PERM not in permissions:
            return Response({'code': 403, 'msg': '无权限管理小程序图标'})

        deny = forbid_display_write_in_all_scope(request)
        if deny:
            return deny

        action = (request.data.get('action') or 'upload').strip()
        club_id = resolve_effective_club_id(request, request.user)
        raw_key = request.data.get('icon_key')
        if raw_key is None or raw_key == '':
            raw_key = request.query_params.get('icon_key')
        if isinstance(raw_key, (list, tuple)):
            raw_key = raw_key[0] if raw_key else ''
        icon_key = str(raw_key or '').strip()
        if icon_key not in MINIAPP_ICON_LABELS:
            return Response({
                'code': 400,
                'msg': (
                    f'icon_key 无效: {icon_key or "(空)"}。'
                    '若上传接单池卡背景，请确认 Django 已 pull 到含 grab_card_* 的提交并重启进程'
                ),
            })

        if action == 'save_meta':
            description = (request.data.get('description') or '').strip()
            row, _ = ClubMiniappIcon.query.get_or_create(
                club_id=club_id,
                icon_key=icon_key,
                defaults={
                    'label': MINIAPP_ICON_LABELS[icon_key],
                    'image_path': default_icon_path(icon_key),
                },
            )
            row.description = description
            row.label = MINIAPP_ICON_LABELS[icon_key]
            row.save(update_fields=['description', 'label', 'UpdateTime'])
            return Response({'code': 0, 'msg': '保存成功'})

        file_obj = request.FILES.get('file')
        if not file_obj:
            return Response({'code': 400, 'msg': '请上传图片'})
        ok, msg = validate_image(file_obj)
        if not ok:
            return Response({'code': 400, 'msg': msg})

        ext = os.path.splitext(file_obj.name)[1].lower() or '.png'
        if ext not in ('.png', '.jpg', '.jpeg', '.webp'):
            ext = '.png'
        import uuid
        stamp = uuid.uuid4().hex[:12]
        # 路径必须含 club_id + 唯一后缀：否则同名覆盖后 CDN 仍显示旧图，且会串俱乐部
        if icon_key in POSTER_ICON_KEYS:
            oss_path = f'{POSTER_FOLDER}/{club_id}_{icon_key}_{stamp}{ext}'
        else:
            oss_path = f'{ICON_FOLDER}/{club_id}/{icon_key}_{stamp}{ext}'

        row = ClubMiniappIcon.query.filter(club_id=club_id, icon_key=icon_key).first()
        old_path = (row.image_path or '').strip() if row else ''

        if hasattr(file_obj, 'seek'):
            try:
                file_obj.seek(0)
            except Exception:
                pass
        if not upload_to_oss(file_obj, oss_path):
            return Response({'code': 500, 'msg': '图片上传失败'})

        if row:
            row.image_path = oss_path
            row.label = MINIAPP_ICON_LABELS[icon_key]
            row.is_active = True
            row.is_uploaded = True
            row.save(update_fields=['image_path', 'label', 'is_active', 'is_uploaded', 'UpdateTime'])
        else:
            ClubMiniappIcon.query.create(
                club_id=club_id,
                icon_key=icon_key,
                label=MINIAPP_ICON_LABELS[icon_key],
                image_path=oss_path,
                is_active=True,
                is_uploaded=True,
            )
        if old_path and old_path != oss_path:
            try:
                delete_from_oss(old_path)
            except Exception:
                pass
        return Response({'code': 0, 'msg': '上传成功', 'data': {'image_path': oss_path}})


class ClubPindaoManageView(APIView):
    """POST /jituan/houtai/pindao-manage"""
    permission_classes = [IsAuthenticated]
    parser_classes = [MultiPartParser, FormParser, JSONParser]

    def post(self, request):
        phone = (request.data.get('phone') or request.data.get('username') or '').strip()
        if not phone:
            return Response({'code': 401, 'msg': '缺少客服账号'})
        kefu, permissions = verify_kefu_permission(request, phone)
        if kefu is None:
            return permissions
        if POPUP_PERM not in permissions:
            return Response({'code': 403, 'msg': '无权限管理频道'})

        action = (request.data.get('action') or 'get').strip()
        club_id = resolve_effective_club_id(request, request.user)

        if action == 'get':
            pindao = get_pindao_payload(club_id)
            images = [
                {
                    'id': img.id,
                    'image_path': img.image_path,
                    'sort_order': img.sort_order,
                }
                for img in ClubPindaoImage.query.filter(club_id=club_id).order_by('sort_order', 'id')
            ]
            return Response({
                'code': 0,
                'data': {
                    'pindao': pindao,
                    'images': images,
                    'folder': PINDAO_FOLDER,
                    **list_response_meta(request),
                },
            })

        deny = forbid_display_write_in_all_scope(request)
        if deny:
            return deny

        if action == 'save':
            channel_no = (request.data.get('channel_no') or '').strip()
            title = (request.data.get('title') or '频道').strip() or '频道'
            row, _ = ClubPindao.query.get_or_create(club_id=club_id, defaults={'title': title})
            row.channel_no = channel_no
            row.title = title
            row.is_active = True
            row.save(update_fields=['channel_no', 'title', 'is_active', 'UpdateTime'])
            return Response({'code': 0, 'msg': '保存成功'})

        if action == 'add_image':
            file_obj = request.FILES.get('file')
            if not file_obj:
                return Response({'code': 400, 'msg': '请上传图片'})
            ok, msg = validate_image(file_obj)
            if not ok:
                return Response({'code': 400, 'msg': msg})
            ext = os.path.splitext(file_obj.name)[1].lower() or '.jpg'
            import random
            import string
            rnd = ''.join(random.choices(string.ascii_lowercase + string.digits, k=8))
            oss_path = f'{PINDAO_FOLDER}/{club_id}_{rnd}{ext}'
            if not upload_to_oss(file_obj, oss_path):
                return Response({'code': 500, 'msg': '图片上传失败'})
            pindao_row, _ = ClubPindao.query.get_or_create(club_id=club_id, defaults={'title': '频道'})
            max_sort = ClubPindaoImage.query.filter(club_id=club_id).order_by('-sort_order').first()
            sort_order = (max_sort.sort_order + 1) if max_sort else 0
            img = ClubPindaoImage.query.create(
                club_id=club_id,
                pindao=pindao_row,
                image_path=oss_path,
                sort_order=sort_order,
            )
            return Response({'code': 0, 'msg': '上传成功', 'data': {'id': img.id, 'image_path': oss_path}})

        if action == 'delete_image':
            img_id = request.data.get('id')
            if not img_id:
                return Response({'code': 400, 'msg': '缺少图片 id'})
            img = ClubPindaoImage.query.filter(club_id=club_id, id=img_id).first()
            if not img:
                return Response({'code': 404, 'msg': '图片不存在'})
            if img.image_path:
                delete_from_oss(img.image_path)
            img.delete()
            return Response({'code': 0, 'msg': '删除成功'})

        return Response({'code': 400, 'msg': 'action 无效'})
