from tortoise.expressions import Q

from app.core.crud import CRUDBase
from app.schemas.weixin import (
    WeixinGroupChatCreate,
    WeixinGroupChatUpdate,
    WeixinGroupChatXingyunCreate,
)

from some_sdk.services.binder import wk_client, lintao_client, xy_client
from some_sdk.wk_weixin_sdk.apis import corp_group
from some_sdk.wk_weixin_sdk.apis.extern_user import get_external_user_chat_info
from some_sdk.xingyun_sdk.apis.work_user import list_work_group
from some_sdk.xingyun_sdk.apis.customer import list_user_join_group

from some_sdk.lintao_sdk.biz.by_order import get_order_relative_user
from some_sdk.lintao_sdk.apis.orderlist import list_product_raw, get_order_log

from app.models.weixin import WeixinGroupChat, RoleType, CustomerGroup
from app.controllers.weixin.user import weixin_user_controller
from app.controllers.weixin.customer import weixin_customer_controller
from app.utils.common import async_split_generator, async_generator_to_list
from app.core.cache import cache_if, invalidate_cache

import re

import logging
logger = logging.getLogger(__name__)

ROLE_LIST = [role.value for role in RoleType]

class WeixinGroupChatController(CRUDBase[WeixinGroupChat, WeixinGroupChatCreate, WeixinGroupChatUpdate]):
    def __init__(self):
        super().__init__(model=WeixinGroupChat)

    async def get_external_group_chat_info(self, chat_id: str):
        group_info = await corp_group.get_external_group_chat_info(wk_client, chat_id)

        internal_member_list = group_info['internal_member_list']
        external_member_list = group_info['external_member_list']
        group_name = group_info.get('name')

        external_member_list.sort(key=lambda user: user.get('join_time'))

        unique_dict = {
            'name': group_name,
            'external_user_count': len(external_member_list),
            'internal_member_count': len(internal_member_list),
        }
        group_info.update(unique_dict)
        # 同步更新数据库
        status, obj = await self.create_or_update(group_info, query_kwargs={'chat_id': chat_id}, update_kwargs=unique_dict)
        if not status:
            logger.debug(f'群聊数据不变，不用更新，chat_id: {chat_id}')
        # elif status == 'create':
        #     await self.create_customer_group(chat_id)
        else:
            # 群更新：触发数据同步事件
            # event_manager.subscribe("group_chat_updated", update_cache_handler, EventPriority.MEDIUM)

            # 只保存准确无误的数据
            # buyer_nick = get_buyer_nick_from_group_name(group_name)
            # logger.debug(f'group_name: {group_name}; buyer_nick: {buyer_nick}')
            # if not buyer_nick:
            #     logger.error(f'群聊未命名，无法绑定订单，chat_id: {chat_id}')
            #     return group_info
            
            # self.load_erp_order_info_by_group(buyer_nick, internal_member_list, external_member_list)

            update_result1 = await weixin_user_controller.update_from_group([*internal_member_list])
            update_result2 = await weixin_customer_controller.update_from_group([*external_member_list])
            logger.debug(f'群聊用户数据更新结果，chat_id: {chat_id}, {update_result1}')
            logger.debug(f'群聊客户数据更新结果，chat_id: {chat_id}, {update_result2}')
            # 刷新用户缓存
            for user in [*internal_member_list, *external_member_list]:
                await self.expire_user_cache(user.get('userid'))
        
        group_info['is_create'] = status == 'create'
        group_info['detect_update'] = status != False
        return group_info
    
    # 从星云有客中加载群聊信息
    async def load_xingyun_group_info(self, chat_name: str=''):
        # 检索出最新的记录，只加载最新的记录
        newest_group = await self.model.filter(xingyun_chat_id__isnull=False).order_by('-create_time').first()
        newest_time = newest_group.create_time if newest_group else 1735660800 # 2025-01-01 00:00:00

        load_result = {"update_count": 0, "add_count": 0}
        group_iter = list_work_group(xy_client, chatName=chat_name)
        async for group_list in async_split_generator(group_iter):
            if group_list[-1].get('createTime') < newest_time:
                break
            logger.debug(f'处理群聊信息，chat_name: {chat_name}, {len(group_list)}')
            result = await self.save_xingyun_group_info(group_list)
            load_result['update_count'] += result['update_count']
            load_result['add_count'] += result['add_count']
            logger.debug(f'群聊数据更新结果，chat_name: {chat_name}, {result}')
            
            if load_result['add_count'] + load_result['update_count'] > 300:
                break

        await self.refresh_xingyun_group_info()
        return load_result
    
    async def save_xingyun_group_info(self, group_list: list):
        group_dict = {group.get('groupChatId'): group for group in group_list}
        group_orm_list = await self.model.filter(chat_id__in=group_dict.keys())

        update_list = []
        history = {}
        for group_orm in group_orm_list:
            group = group_dict.pop(group_orm.chat_id, history.get(group_orm.chat_id, {}))
            if not group: continue
            history[group_orm.chat_id] = group

            try:
                group_in = WeixinGroupChatXingyunCreate(**group)
            except Exception as e:
                logger.error(f'群聊数据转换错误，chat_id: {group}, {e}')
                continue
            updated = False
            if group_in.avatars:
                group_orm.avatars = group_in.avatars
                updated = True
            if group_orm.xingyun_chat_id != group_in.xingyun_chat_id:
                group_orm.xingyun_chat_id = group_in.xingyun_chat_id
                updated = True
            if updated:
                update_list.append(group_orm)
        if update_list:
            await self.model.bulk_update(update_list, ['avatars', 'xingyun_chat_id'])
        
        add_list = []
        for chat_id, group in group_dict.items():
            group_in = WeixinGroupChatXingyunCreate(**group)
            add_list.append(self.model(**group_in.model_dump(exclude_unset=True)))
        
        if add_list:
            await self.model.bulk_create(add_list)
        
        return {
            'update_count': len(update_list),
            'add_count': len(add_list),
        }

    # 刷新数据库中的群聊信息
    async def refresh_xingyun_group_info(self):

        for _ in range(10):
            group_orm_list = await self.model.filter(xingyun_chat_id__isnull=False, external_user_count__isnull=True).order_by('-create_time').limit(20).all()
            if not group_orm_list: break
            logger.debug(f'刷新群聊数据，{len(group_orm_list)}')
            
            for group_orm in group_orm_list:
                try:
                    await self.get_external_group_chat_info(group_orm.chat_id)
                except Exception as e:
                    logger.error(f'刷新群聊数据错误，chat_id: {group_orm.chat_id}, {e}')
                    continue
                logger.debug(f'刷新群聊数据结果，chat_id: {group_orm.name} 已更新')
    
    # 同步erp中的用户和客户信息到数据库
    async def load_erp_order_info_by_group(self, buyer_nick: str, internal_member_list: list, external_member_list: list):
        if not buyer_nick:
            logger.error(f'群聊未命名，无法绑定订单，buyer_nick: {buyer_nick}')
            return

        orders = await async_generator_to_list(get_order_relative_user(lintao_client, buyer_nick=buyer_nick))
        assert orders, f'未找到订单，buyer_nick: {buyer_nick}'

        internal_member_dict = {user.get('name'): user for user in internal_member_list}

        order = orders[0]

        order_relative_user = order.get("users", [])
        order_relative_user_dict = {user.get('name'): user for user in order_relative_user}
        
        for name, user in order_relative_user_dict.items():
            erp_id = user.get('id', '')
            if not erp_id: continue
            if re.match(r'^\d+$', erp_id) is None: 
                # 客户
                if not external_member_list:
                    logger.error(f'客户群聊用户数为0，无法绑定客户, name: {name}, erp_id: {erp_id}')
                    continue
                if name != buyer_nick:
                    logger.error(f'客户群聊用户与ERP卖家名称不一致，无法绑定客户, name: {name}, erp_id: {erp_id}')
                    continue
                if len(external_member_list) != 1: 
                    external_member_list.sort(key=lambda user: user.get('join_time'))
                    logger.warning(f'客户群聊用户数不是1个，将选取最先入群的用户作为客户，name: {name}, erp_id: {erp_id}')

                    for member in external_member_list:
                        member['order_id'] = order.get('trade_no')
                    
                weixin_user = external_member_list[0]
                weixin_user.update({
                    'order_id': order.get('trade_no'),
                    'taobao_id': user.get('id', ''),
                    'taobao_name': user.get('name', ''),
                    'erp_message': user.get('message', ''),
                    'erp_remark': user.get('memo', ''),
                    'need_confirm': len(external_member_list) > 1,
                })

                continue
            else:
                # 员工
                erp_id = int(erp_id)
                weixin_user = internal_member_dict.get(name)
                logger.debug(f'name: {name}, erp_id: {erp_id}, weixin_user: {weixin_user}')
                if not weixin_user:
                    logger.error(f'{internal_member_dict.keys()} {name}')
                    logger.error(f'客户群聊用户与ERP员工名称不一致，无法绑定员工, name: {name}, erp_id: {erp_id}')
                    continue
                weixin_user.update({
                    'erp_id': erp_id,
                    'erp_name': name,
                    'role': user.get('role', ''),
                })
                continue
    
    # 通过客户ID获取客户的所有订单
    async def get_order_relative_user_list_by_weixin_userid(self, user_id: str):
        customers = await weixin_customer_controller.model.filter(weixin_id=user_id)
        if not customers: 
            await weixin_customer_controller.create({
                "weixin_id": user_id,
            })
            # 新用户：触发数据同步事件
            return False, []

        order_list = []
        buyer_set = set()
        for customer in customers:
            buyer_nick = customer.taobao_name
            buyer_id = customer.taobao_id
            if buyer_nick:
                logger.debug(f'name: {user_id}; buyer_nick: {buyer_nick}')
                if buyer_nick in buyer_set: continue
                buyer_set.add(buyer_nick)
                orders = await async_generator_to_list(get_order_relative_user(lintao_client, buyer_nick=buyer_nick))
            elif buyer_id:
                if buyer_id in buyer_set: continue
                buyer_set.add(buyer_id)
                orders = await async_generator_to_list(get_order_relative_user(lintao_client, buyer_id=buyer_id))
            else:
                assert buyer_nick, "当前客户未绑定淘宝账号"

            logger.debug(f'orders.length: {len(orders)}')
            order_list.extend(orders)

            # for order in orders:
        # 原地按照id排序
        order_list.sort(key=lambda order: order.get('id'), reverse=True)
        if order_list:
            await self.get_user_detail_by_order(order=order_list[0])
        
        return True, order_list
    
    # 根据客户名字，获取群聊中客户的所有订单
    async def get_order_relative_user_list_by_weixin_group_name(self, buyer_nick: str):
        async with cache_if(f'order:relative_user:{buyer_nick}', ttl=10) as cache:
            if cache.hit:
                order_list = cache.value
                logger.debug(f'{cache.key} hit')
            else:
                logger.debug(f'{cache.key} not hit')
                order_list = await async_generator_to_list(get_order_relative_user(lintao_client, buyer_nick=buyer_nick))
                cache.set(order_list)
        logger.debug(f'order_list.length: {len(order_list)}')

        # for order in order_list:
        order_list.sort(key=lambda order: order.get('id'), reverse=True)
        if order_list:
            await self.get_user_detail_by_order(order=order_list[0])
            order_list[0]['__type__'] = 'load_order_by_weixin_group_name'
        
        return order_list

    # 根据客户ID，获取群聊中客户的所有订单
    async def get_order_relative_user_list_by_weixin_group_buyer_id(self, buyer_id: str):
       
        orders = await async_generator_to_list(get_order_relative_user(lintao_client, buyer_id=buyer_id))
        logger.debug(f'orders.length: {len(orders)}')

        # for order in orders:
        if orders:
            await self.get_user_detail_by_order(order=orders[0])
        
        return orders
    
    async def get_user_detail_by_order(self, order_id: str='', order: dict = None):
        if not order:
            orders = await async_generator_to_list(get_order_relative_user(lintao_client, trade_no=order_id))
            if not orders: return
            _orders = [o for o in orders if o.get('ctid') == order_id]
            # assert len(orders) == 1, f'订单号 {order_id} 对应多个订单'
            if not _orders: 
                for order in orders:
                    logger.warning(f'订单号 {order_id} 对应多个订单，{order}')
                # return {}
                _orders = orders
            
            order = _orders[0]
        
        # 缓存订单产品信息
        tid = order.get("ctid")
        async with cache_if(f'order:product:{tid}', ttl=3600*24) as cache:
            if cache.hit:
                product_resp = cache.value
            else:
                product_resp = (await list_product_raw(lintao_client, tid=tid)).get('data', {})
                if product_resp: cache.set(product_resp)
            
            if product_resp:
                order['product_title'] = product_resp[0].get("title")
                order['product_pic'] = product_resp[0].get("pic_path")
        
        order['has_fetched_user_detail'] = True
        user_list = order.get("users", [])

        async with cache_if(f'user:auto_relate', ttl=600) as cache:
            if cache.hit:
                default_user_list = cache.value
            else:
                default_user_list = await weixin_user_controller.all(Q(auto_relate=True))
                default_user_list = [user.to_dict() for user in default_user_list]
                cache.set(default_user_list)
            default_user_set = {str(user.get('erp_id')) for user in default_user_list}

        for user in user_list:
            erp_id = user.get('id', '')
            if erp_id in default_user_set: continue
            await self.get_order_user_info(user)
        
        order['users'].extend(default_user_list)

        # 根据 role_list 中的顺序进行排序
        role_order = {role: index for index, role in enumerate(ROLE_LIST)}
        order['users'].sort(key=lambda user: role_order.get(user['role'], len(ROLE_LIST)))

        return order
    
    async def get_order_user_info(self, user: dict=None):
        if not user: return
        erp_id = user.get('id', '')
        if not erp_id: return
        if re.match(r'^\d+$', erp_id) is None:
            # logger.debug(f'淘宝客户, erp_id: {erp_id}, user: {user}')
            # 客户
            taobao_id = user.get('id', '')
            query = Q(taobao_id=taobao_id)
            weixin_customer_list = await weixin_customer_controller.all(query)
            if not weixin_customer_list:
                logger.error(f'客户未绑定订单, taobao_id: {taobao_id}, user: {user}')
                return
            weixin_customer = weixin_customer_list[0]
            buyer = weixin_customer.to_dict()
            if not buyer.get('name') and user.get('name'): 
                weixin_customer.taobao_name = user.get('name')
                await weixin_customer.save()
            user.update({**buyer, **user})
        else:
            # 员工
            erp_id = int(erp_id)
            # logger.debug(f'员工, erp_id: {erp_id}, user: {user}')
            query = Q(erp_id=erp_id)
            weixin_user_list = await weixin_user_controller.all(query)
            if not weixin_user_list:
                user['erp_id'] = erp_id
                logger.error(f'员工未绑定ERP, erp_id: {erp_id}, user: {user}')
                return
            weixin_user = weixin_user_list[0]
            user.update(weixin_user.to_dict())

    # 获取erp日志
    async def get_erp_order_log(self, order_id: str):
        return await get_order_log(lintao_client, order_id)
    
    async def expire_user_cache(self, weixin_id: str):
        await invalidate_cache(f'customer:user_datail:{weixin_id}')
        await invalidate_cache(f'customer:user_datail_0:{weixin_id}')
    
    # async def list_user_join_group(self, xingyun_id: int):
    #     assert xingyun_id, 'id 不能为空'
    #     result = await async_generator_to_list(list_user_join_group(xy_client, cid=xingyun_id))

    #     xingyun_chat_ids = [item.get('id') for item in result]
    #     all_group_chat = await self.model.filter(xingyun_chat_id__in=xingyun_chat_ids)
    #     group_chat_dict = {item.xingyun_chat_id: item for item in all_group_chat}
    #     logger.debug(f'list_user_join_group, xingyun_chat_ids: {xingyun_chat_ids}')

    #     remain_chat_ids = set()
    #     for item in result:
    #         group_chat_id = item.get('id')
    #         if group_chat_id in group_chat_dict: continue
    #         remain_chat_ids.add(group_chat_id)

    #         chat_name = item.get('chatName')
    #         if not chat_name: continue
    #         await self.load_xingyun_group_info(chat_name=chat_name)
        
    #     remain_chat_list = await self.model.filter(xingyun_chat_id__in=remain_chat_ids)
    #     all_group_chat.extend(remain_chat_list)
    #     return all_group_chat

weixin_group_chat_controller = WeixinGroupChatController()
