"""俱乐部微信登录（多 openid 绑定，不修改旧 wechatlogin 逻辑）。"""
import logging
import random
import time
import uuid

from django.db import transaction
from django.utils import timezone
from rest_framework_simplejwt.tokens import RefreshToken

from jituan.constants import CLUB_ID_DEFAULT
from jituan.models import UserWxOpenid
from jituan.services.club_resolver import jscode2session, resolve_club_by_appid
from jituan.services.club_user import (
    ensure_user_club_id,
    ensure_wx_openid_binding,
    find_user_by_wx_openid,
    resolve_or_create_wx_user,
)
from users.business_models import User
from users.models import UserBoss, UserDashou, UserGuanshi, UserShangjia, UserZuzhang, UserShenheguan
from gvsdsdk.models import Role

logger = logging.getLogger(__name__)


def _generate_user_uid():
    for _ in range(10):
        timestamp_part = str(int(time.time()))[-5:].zfill(5)
        random_part = str(random.randint(0, 99)).zfill(2)
        user_id = timestamp_part + random_part
        if len(user_id) == 7 and user_id.isdigit():
            if not User.query.filter(UserUID=user_id).exists():
                return user_id
    raise RuntimeError('生成用户ID失败')


def _ensure_boss_profile(user):
    try:
        UserBoss.query.get(user=user)
    except UserBoss.DoesNotExist:
        UserBoss.query.create(user=user, nickname='板板大人')


def _ensure_consumer_role(user):
    from users.business_models import UserRole as BizUserRole
    normal_role = Role.objects.filter(RoleName='消费者').first()
    if not normal_role:
        return
    exists = BizUserRole.objects.filter(UserUUID=user.UserUUID, RoleUUID=normal_role.RoleUUID).exists()
    if not exists:
        BizUserRole.objects.create(
            UserRoleUUID=uuid.uuid4().bytes,
            UserUUID=user.UserUUID,
            RoleUUID=normal_role.RoleUUID,
            CompanyUUID=uuid.UUID('b0000000-0000-0000-0000-000000000001').bytes,
        )


def _collect_role_status(user):
    dashou_status = None
    shangjia_status = None
    guanshi_status = None
    zuzhang_status = None
    kaoheguan_status = 0
    boss_nickname = '微信用户'

    try:
        boss = UserBoss.query.get(user=user)
        boss_nickname = boss.nickname or '微信用户'
    except UserBoss.DoesNotExist:
        pass

    try:
        UserDashou.query.get(user=user)
        dashou_status = 1
    except UserDashou.DoesNotExist:
        dashou_status = None

    try:
        UserShangjia.query.get(user=user)
        shangjia_status = 1
    except UserShangjia.DoesNotExist:
        shangjia_status = None

    try:
        UserGuanshi.query.get(user=user)
        guanshi_status = 1
    except UserGuanshi.DoesNotExist:
        guanshi_status = None

    try:
        UserZuzhang.query.get(user=user)
        zuzhang_status = 1
    except UserZuzhang.DoesNotExist:
        zuzhang_status = None

    try:
        kg = UserShenheguan.query.get(user=user)
        kaoheguan_status = 1 if kg.zhuangtai == 1 else 0
    except UserShenheguan.DoesNotExist:
        kaoheguan_status = 0

    return {
        'dashou_status': dashou_status,
        'shangjia_status': shangjia_status,
        'guanshi_status': guanshi_status,
        'zuzhang_status': zuzhang_status,
        'kaoheguan_status': kaoheguan_status,
        'boss_nickname': boss_nickname,
    }


def login_or_register_by_club(code, club_id=None, app_id=None, client_ip=''):
    """
    俱乐部微信登录核心逻辑。
    - 通过 user_wx_openid(club_id, openid) 定位用户
    - xq 俱乐部兼容：若绑定不存在但 User.OpenID 已存在，则自动建绑定（不新建用户）
    """
    wx_data = jscode2session(code, club_id=club_id, app_id=app_id)
    if not wx_data or 'openid' not in wx_data:
        return None, wx_data.get('errmsg', '微信授权失败')

    openid = wx_data['openid']
    unionid = wx_data.get('unionid', '')
    wx_appid = wx_data.get('wx_appid', '') or ''
    resolved_club_id = wx_data.get('club_id') or club_id or CLUB_ID_DEFAULT

    with transaction.atomic():
        binding = UserWxOpenid.query.filter(
            club_id=resolved_club_id, openid=openid
        ).first()

        user = None
        created = False

        if binding:
            user = User.query.filter(UserUID=binding.yonghuid).first()
            if not user:
                user = User.objects.filter(UserUID=binding.yonghuid).first()

        if not user:
            user, created = resolve_or_create_wx_user(
                resolved_club_id, openid, _generate_user_uid,
                unionid=unionid, wx_appid=wx_appid,
            )
            if created:
                _ensure_boss_profile(user)
                _ensure_consumer_role(user)
        else:
            ensure_wx_openid_binding(
                resolved_club_id, openid, user, unionid, wx_appid=wx_appid,
            )

        if unionid and unionid != (user.UnionID or ''):
            user.UnionID = unionid
        if client_ip:
            user.IP = client_ip
        user.UserLastLoginDate = timezone.now()
        user.save()

        ensure_user_club_id(user, resolved_club_id)

    roles = _collect_role_status(user)
    refresh = RefreshToken.for_user(user)
    token = str(refresh.access_token)

    staff_fields = {}
    order_counts = {}
    group_info = {}
    try:
        from merchant_ops.services.authz import staff_fields_for_login
        staff_fields = staff_fields_for_login(user) or {}
    except Exception:
        logger.exception('staff_fields_for_login 失败 uid=%s', getattr(user, 'UserUID', ''))

    try:
        from users.views import WechatMiniProgramLoginView
        login_view = WechatMiniProgramLoginView()
        order_counts = login_view.jisuanOrderShuliang(user.UserUID) or {}
        group_info = login_view.huoquQunPeizhi() or {}
    except Exception:
        logger.exception('登录附属信息失败 uid=%s', getattr(user, 'UserUID', ''))

    data = {
        'token': token,
        'nicheng': roles['boss_nickname'],
        'uid': user.UserUID,
        'touxiang': user.Avatar or '',
        'shangjiastatus': roles['shangjia_status'],
        'dashoustatus': roles['dashou_status'],
        'guanshistatus': roles['guanshi_status'],
        'zuzhangstatus': roles['zuzhang_status'],
        'kaoheguanstatus': roles['kaoheguan_status'],
        'dingdantiaoshu': order_counts,
        'dashouqun': group_info.get('dashouqun', ''),
        'dashouqunid': group_info.get('dashouqunid', ''),
        'guanshiqun': group_info.get('guanshiqun', ''),
        'guanshiqunid': group_info.get('guanshiqunid', ''),
        'club_id': resolved_club_id,
        'is_new_user': created,
        **staff_fields,
    }
    return data, None


def refresh_wx_openid_binding(code, user, club_id=None, app_id=None):
    """已登录用户：用当前小程序 code 刷新 user_wx_openid（不换 JWT）。"""
    wx_data = jscode2session(code, club_id=club_id, app_id=app_id)
    if not wx_data or 'openid' not in wx_data:
        return None, wx_data.get('errmsg', '微信授权失败')

    openid = wx_data['openid']
    unionid = wx_data.get('unionid', '')
    wx_appid = wx_data.get('wx_appid', '') or ''
    resolved_club_id = wx_data.get('club_id') or club_id or CLUB_ID_DEFAULT

    ensure_wx_openid_binding(resolved_club_id, openid, user, unionid, wx_appid=wx_appid)
    ensure_user_club_id(user, resolved_club_id)
    if unionid and unionid != (getattr(user, 'UnionID', None) or ''):
        user.UnionID = unionid
        user.save(update_fields=['UnionID'])

    return {
        'club_id': resolved_club_id,
        'openid_preview': openid[:6] + '...' + openid[-4:] if len(openid) > 10 else openid,
        'wx_appid': wx_data.get('wx_appid', ''),
    }, None


def login_or_register_by_official_oauth(code, club_id=None, client_ip=''):
    """
    服务号网页授权登录（H5）。
    换 openid 用 club.official_appid/secret；建用户逻辑与小程序登录一致。
    """
    from jituan.services.club_resolver import oauth2_access_token

    wx_data = oauth2_access_token(code, club_id=club_id)
    if not wx_data or 'openid' not in wx_data:
        return None, (wx_data or {}).get('errmsg', '微信授权失败')

    openid = wx_data['openid']
    unionid = wx_data.get('unionid', '')
    wx_appid = wx_data.get('wx_appid', '') or ''
    resolved_club_id = wx_data.get('club_id') or club_id or CLUB_ID_DEFAULT

    with transaction.atomic():
        binding = UserWxOpenid.query.filter(
            club_id=resolved_club_id, openid=openid
        ).first()

        user = None
        created = False

        if binding:
            user = User.query.filter(UserUID=binding.yonghuid).first()
            if not user:
                user = User.objects.filter(UserUID=binding.yonghuid).first()

        if not user:
            user, created = resolve_or_create_wx_user(
                resolved_club_id, openid, _generate_user_uid,
                unionid=unionid, wx_appid=wx_appid,
            )
            if created:
                _ensure_boss_profile(user)
                _ensure_consumer_role(user)
        else:
            ensure_wx_openid_binding(
                resolved_club_id, openid, user, unionid, wx_appid=wx_appid,
            )

        if unionid and unionid != (user.UnionID or ''):
            user.UnionID = unionid
        if client_ip:
            user.IP = client_ip
        user.UserLastLoginDate = timezone.now()
        user.save()

        ensure_user_club_id(user, resolved_club_id)

    roles = _collect_role_status(user)
    refresh = RefreshToken.for_user(user)
    token = str(refresh.access_token)

    staff_fields = {}
    order_counts = {}
    group_info = {}
    try:
        from merchant_ops.services.authz import staff_fields_for_login
        staff_fields = staff_fields_for_login(user) or {}
    except Exception:
        logger.exception('staff_fields_for_login 失败 uid=%s', getattr(user, 'UserUID', ''))

    try:
        from users.views import WechatMiniProgramLoginView
        login_view = WechatMiniProgramLoginView()
        order_counts = login_view.jisuanOrderShuliang(user.UserUID) or {}
        group_info = login_view.huoquQunPeizhi() or {}
    except Exception:
        logger.exception('登录附属信息失败 uid=%s', getattr(user, 'UserUID', ''))

    data = {
        'token': token,
        'nicheng': roles['boss_nickname'],
        'uid': user.UserUID,
        'touxiang': user.Avatar or '',
        'shangjiastatus': roles['shangjia_status'],
        'dashoustatus': roles['dashou_status'],
        'guanshistatus': roles['guanshi_status'],
        'zuzhangstatus': roles['zuzhang_status'],
        'kaoheguanstatus': roles['kaoheguan_status'],
        'dingdantiaoshu': order_counts,
        'dashouqun': group_info.get('dashouqun', ''),
        'dashouqunid': group_info.get('dashouqunid', ''),
        'guanshiqun': group_info.get('guanshiqun', ''),
        'guanshiqunid': group_info.get('guanshiqunid', ''),
        'club_id': resolved_club_id,
        'is_new_user': created,
        'login_client': 'h5',
        'wx_appid': wx_appid,
        **staff_fields,
    }
    return data, None
