from tortoise.exceptions import IntegrityError
from app.core.crud import CRUDBase
from app.schemas.msg import (
    MsgCreate,
    MsgUpdate,
    MsgNewOrder,
    FollowFormErp,
    MsgType
)
import httpx
from app.models.msg import Msg, Follow
from app.models.weixin import WeixinCustomer, WeixinUser
from some_sdk.wk_weixin_sdk.apis.extern_user import get_external_user_chat_info
from some_sdk.services.binder import lintao_client, feishu_client
from some_sdk.lintao_sdk.biz.by_order import get_order_relative_user
from some_sdk.feishu_sdk.apis.doc import batch_create as create_feishu_records

from datetime import datetime, timedelta
from app.utils.common import async_split_generator, split_generator, gen_random_str
from typing import List
import re

import hashlib

import logging
logger = logging.getLogger(__name__)

import asyncio
_sync_to_feishu_lock = asyncio.Lock()

class MsgController(CRUDBase[Msg, MsgCreate, MsgUpdate]):
    def __init__(self):
        super().__init__(model=Msg)

    async def send_to_wexin(self, data:dict ):
        # pass
        url = 'https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=57ba9cd5-2c62-43dd-bfea-78c7b4073128'

        async with httpx.AsyncClient() as client:
            resp = await client.post(url,
                headers={"Content-Type": "application/json"},
                json=data,
            )
            data = resp.json()
            print(data)
            return data

    async def send_order_to_weixin(self, msg: Msg):
        """
        极简订单通知：仅展示店铺、旺旺ID、金额、归属客服
        """
        url = 'https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=57ba9cd5-2c62-43dd-bfea-78c7b4073128'

        order_list = msg.detail or []
        if not order_list:
            logger.warning("订单详情为空，跳过发送")
            return

        order = order_list[0]
        # users = order.get("users", [])
        # buyer = next((u for u in users if u.get("role") == "buyer"), None)

        # 关键字段
        shop_name = order.get("shop_name", "未知店铺")
        buyer_name = msg.title
        # buyer_name = buyer.get("name") if buyer else ""
        # buyer_name = buyer_name or msg.content.split(")", 1)[0].split("(")[1]

        is_refund = order.get("is_refund", 0) > 0
        msg_title = "💰 用户退款" if is_refund else "🛒 新订单"

        real_payment = order.get("real_payment", "0.00")
        qiwei_name = msg.owner_name or "未知客服"

        # 极简 Markdown
        markdown_content = f"""# {msg_title}\n

**店铺**：{shop_name}  
**旺旺ID**：`{buyer_name}`  
**金额**：¥{real_payment}  
**企微客服**：{qiwei_name}  
**订单编号**：{order.get("trade_no", "未知订单号")}  
"""

        data = {
            "msgtype": "markdown",
            "markdown": {
                "content": markdown_content
            }
        }
        result = await self.send_to_wexin(data)
        logger.info(f"企业微信极简订单通知发送结果: {result}")

    
    async def parse_order_msg(self, msg: Msg, send_set: set, msg_dict: dict):
        title = msg.title
        try: 
            if title not in send_set:
                send_set.add(title)
                # try: await self.send_to_wexin(msg)
                owner_name = '、'.join([ (name or '').split('（')[0].split('vip客服-')[-1].split('-印刷定制')[0] for name in msg_dict[title] ])msg.owner_name = owner_name

                try: await self.send_order_to_weixin(msg)
                except Exception as e:
                    logger.error(f'发送订单消息到微信失败，{e}')
                    return

                # await self.send_to_wexin(msg, mentioned_list=msg_dict[title])
                logger.info(f'发送消息到微信成功，{msg.content}')
            
            msg.is_send = True
            msg.send_at = datetime.now()
            await msg.save()
        except Exception as e:
            logger.error(f'发送消息到微信失败，{e}')

    async def new_system_msg(self, title: str, content: str, owner_name: str = None):
        await self.create(
            dict(
                hash_id=hashlib.md5(f'{title}{content}{owner_name}'.encode()).hexdigest(),
                title=title,
                content=content,
                type=MsgType.SYSTEM,
                owner_name=owner_name,
            )
        )
    
    async def send_system_msg(self, msg: Msg):
        msg.send_at = datetime.now()
        markdown_content = f"""# 📣 系统通知 \n
## {msg.title} \n
{msg.content} \n

{msg.send_at.strftime("%Y-%m-%d %H:%M:%S")}
"""
        
        data = {
            "msgtype": "markdown",
            "markdown": {
                "content": markdown_content
            }
        }
        result = await self.send_to_wexin(data)
        logger.info(f"企业微信极简订单通知发送结果: {result}")
        
        msg.is_send = True
        await msg.save()
    
    async def sync_msg(self):
        msg_list = await self.model.filter(is_send=False)

        msg_dict = {}
        for msg in msg_list:
            title = msg.title
            msg_dict[title] = msg_dict.get(title, []) + [msg.owner_name]
        
        send_set = set()
        for msg in msg_list:
            title = msg.title
            if msg.type == MsgType.NEW_ORDER:
                await self.parse_order_msg(msg, send_set, msg_dict)
            elif msg.type == MsgType.SYSTEM:
                await self.send_system_msg(msg)

    async def fill_customer_info(self):
        msg_orm_list = await self.model.filter(id__gt=306)

        update_list = []
        for msg in msg_orm_list:
            detail = msg.detail or []
            taobao_name = msg.title

            detail_list = []
            for order_item in detail:
                customer_orm = await WeixinCustomer.filter(taobao_name=taobao_name).first()
                if not customer_orm:
                    logger.warning(f'未找到淘宝用户{taobao_name}的企微客户')
                    continue

                for user in order_item.get("users", []):
                    if user.get("role") != "buyer": continue
                    user.update(customer_orm.to_dict())
                    break

                detail_list.append(order_item)

            if detail_list:
                msg.detail = detail_list
                update_list.append(msg)
        
        if update_list:
            await self.model.bulk_update(update_list, fields=['detail'])
                
    
    async def new_order(self, order_id: str, customer_orm: WeixinCustomer, is_refund: bool = False):

        msg_set = set()
        msg_list = []
        now = datetime.now()

        order_list = get_order_relative_user(lintao_client, order_id)
        order_unique_list = {}
        async for order in order_list:
            order_state_string = order.get('order_state_string')
            trade_no = order.get('trade_no')
            if not is_refund and order_state_string not in ['待领单', '待抢单']:
                logger.warning(f'订单{trade_no} 状态为{order_state_string}，跳过')
                continue

            remark = order.get('remark')
            if not is_refund and remark and '企微联系' in remark:
                logger.warning(f'订单{trade_no} 状态为{order_state_string}， 备注：{remark}, 已备注企微联系，跳过')
                continue

            create_time = order.get('create_time')
            if create_time and not is_refund:
                create_time = datetime.fromisoformat(create_time.replace("Z", "+00:00"))
                if (now - create_time).total_seconds() > 3600: 
                    logger.warning(f'订单{order_id} 创建时间({create_time})与当前时间({now})相差超过60秒，跳过')
                    continue

            if trade_no not in order_unique_list:
                order_unique_list[trade_no] = order
                logger.info(f'订单{order_id} 订单号{trade_no} 创建时间{create_time} 订单状态：{order_state_string} {order.get("title")}')

                # 填充买家信息
                for user in order.get("users", []):
                    if user.get("role") != "buyer": continue
                    user.update(customer_orm.to_dict())
                    break
                
        
        if not order_unique_list:
            logger.warning(f'订单{order_id} 没有符合条件的订单，跳过')
            return
        
        chat_info = await get_external_user_chat_info(customer_orm.weixin_id)
        follow_user_list = chat_info.get('follow_user', [])

        order_list = list(order_unique_list.values())
        order_info = [
                f"在({order.get('shop_name')})下单{order.get('price')}元，单号({order.get('trade_no')})"
                for order in order_list
            ]
        for follow_user in follow_user_list:
            follow_userid = follow_user.get('userid')
            weixin_user_orm: WeixinUser = await WeixinUser.filter(userid=follow_userid).first()
            owner_name = '未知'
            if weixin_user_orm: owner_name = weixin_user_orm.english_name or weixin_user_orm.username

            qiwei_customer_name = customer_orm.taobao_name or customer_orm.weixin_name

            content = f"{'退款' if is_refund else ''}订单({qiwei_customer_name}) -({owner_name})- 刚{', '.join(order_info)}"
            logger.info(f'新订单通知:{content}')
            msg_hash_id = hashlib.md5(content.encode('utf-8')).hexdigest()
            if msg_hash_id in msg_set: continue
            msg_set.add(msg_hash_id)

            msg = self.model(
                hash_id=msg_hash_id,
                title=qiwei_customer_name,
                content=content,
                detail=order_list,
                type=MsgType.NEW_ORDER,
                owner_id=follow_userid,
                owner_name=owner_name
            )
            msg_list.append(msg)

        if msg_list:
            try: await self.model.bulk_create(msg_list)
            except IntegrityError as e: 
                if "Duplicate entry" in str(e) and "hash_id" in str(e):
                    logger.info("检测到重复消息，已跳过")
                    # 忽略或处理重复
                else:
                    # 其他完整性错误（如外键失败），应重新抛出
                    raise
        
    async def get_order_user_days_before(self, days: int):
        now = datetime.now().replace(hour=0, minute=0, second=0, microsecond=0)
        start_date, otherMemo = (now - timedelta(days=days)).strftime("%Y-%m-%d %H:%M:%S"), "企微"

        # 琪琪——松屿，小小丽——麦子，小小北——大喜，小泉——苏苏，小洋——东东，蓝莓——小满
        index = 0
        update_list, add_list = [], []
        order_iter_list = [
            (get_order_relative_user(lintao_client, start_date=start_date, otherMemo=otherMemo), ''),
            (get_order_relative_user(lintao_client, start_date=start_date, customer='琪琪'), '松屿'),
            (get_order_relative_user(lintao_client, start_date=start_date, customer='小小丽'), '麦子'),
            (get_order_relative_user(lintao_client, start_date=start_date, customer='小小北'), '大喜'),
            (get_order_relative_user(lintao_client, start_date=start_date, customer='小泉'), '苏苏'),
            (get_order_relative_user(lintao_client, start_date=start_date, customer='小洋'), '东东'),
            (get_order_relative_user(lintao_client, start_date=start_date, customer='蓝莓'), '小满'),
        ]
        for order_iter, staff_name in order_iter_list:
            async for order_list in async_split_generator(order_iter, 10):
                order_dict = {}
                for order in order_list:
                    designer_list = list(filter(lambda x: x.get("role") == "desiger", order.get("users", [])))
                    designer = designer_list[0] if designer_list else None
                    if not designer: continue

                    name = designer.get("name", "")
                    if not name: continue

                    key = tuple([order.get("trade_no", ""), name])
                    if key in order_dict: continue
                    order_dict[key] = order
                    index += 1
                
                _update_list, _add_list = await self.process_order_dict(order_dict, staff_name=staff_name)

                if _update_list and _add_list:
                    logger.info(f'第{index}个订单 处理 {len(_update_list)} 条更新记录， {len(_add_list)} 条新增记录')
                    update_list.extend(_update_list)
                    add_list.extend(_add_list)
        
        print(start_date)
        _update_list, _add_list = [], []

        async with _sync_to_feishu_lock:
            task_id = gen_random_str()
            _update_list, _add_list = await self.sync_to_feishu(task_id)

        return {
            "update_count": len(update_list),
            "add_count": len(add_list),
            "add_count_to_feishu": len(_add_list),
            "update_count_to_feishu": len(_update_list),
            "start_date": start_date,
            "remark": otherMemo
        }

    async def process_order_dict(self, order_dict: dict, staff_name: str = ''):
        async def to_follow_orm(order_info: dict):
            follow_orm = Follow(**FollowFormErp(**order_info).model_dump())
            # print(follow_orm.order_id, order_info.get("users", []))

            for user in order_info.get("users", []):
                if user.get("role") == "desiger":
                    follow_orm.designer_id = user.get("id", "")
                    follow_orm.designer_name = user.get("name", "")
                elif user.get("role") == "taobao_kefu":
                    follow_orm.kefu_id = user.get("id", "")
                    follow_orm.kefu_name = user.get("name", "")
                elif user.get("role") == "buyer":
                    follow_orm.customer_taobao_id = user.get("id", "")
                    follow_orm.customer_name = user.get("name", "")

                    CustomerUser = await WeixinCustomer.filter(taobao_id=follow_orm.customer_taobao_id).first()
                    if CustomerUser:
                        follow_orm.customer_id = CustomerUser.id
            
            # 企微员工
            if staff_name:
                follow_orm.staff_name = staff_name
                staff_orm = await WeixinUser.filter(english_name=f"{follow_orm.staff_name}-印刷定制").first()
                if staff_orm:
                    follow_orm.staff_id = staff_orm.userid
            else:
                remark = follow_orm.remark
                if remark:
                    staff_name_match = re.search(r"企微联系(.*?)拉群", remark)
                    if staff_name_match:
                        follow_orm.staff_name = staff_name_match.group(1).strip()
                    if follow_orm.staff_name:
                        staff_orm = await WeixinUser.filter(english_name=f"{follow_orm.staff_name}-印刷定制").first()
                        if staff_orm:
                            follow_orm.staff_id = staff_orm.userid
                    
                    if not staff_name_match:
                        follow_orm.staff_name = remark
            
            return follow_orm
        
        update_list = []
        follow_list = await Follow.filter(order_id__in=[key[0] for key in order_dict.keys()])
        keys, update_keys = Follow.get_all_keys(exclude_fields=['id', 'updated_at', 'created_at', 'feishu_record_id', 'is_update_to_feishu', 'is_add_to_feishu']), set()
        for follow in follow_list:
            key = tuple([follow.order_id, follow.designer_name])
            if key not in order_dict: continue

            order_info = order_dict.pop(key, None)
            follow_orm = await to_follow_orm(order_info)
            # 比较是否一样，不一样的话，更新
            updated_dict = {}
            for key in keys:
                origin_value = str(getattr(follow, key))
                value = str(getattr(follow_orm, key))
                if origin_value != value:
                    update_keys.add(key)
                    setattr(follow, key, value)
                    updated_dict[key] = f'{origin_value} -> {value}'

            if updated_dict:
                follow_orm.is_update_to_feishu = False
                update_keys.add('is_update_to_feishu')
                update_list.append(follow)
                logger.info(f'订单 {follow.order_id} 设计员 {follow.designer_name} 更新字段 {updated_dict}')

        if update_list:
            await Follow.bulk_update(update_list, fields=update_keys)
            
        add_list = []
        for key, order_info in order_dict.items():
            follow_orm = await to_follow_orm(order_info)
            add_list.append(follow_orm)
        
        if add_list:
            await Follow.bulk_create(add_list)

        return update_list, add_list
    
    async def sync_to_feishu(self, task_id: str):

        add_list = []
        # 需要追加的记录
        follow_list = await Follow.filter(is_update_to_feishu=False, feishu_record_id__isnull=True)
        if follow_list:
            for item_list in split_generator(follow_list, 100):
                result = await create_feishu_records(
                    feishu_client,
                    app_token="HPiNbbW3YaYhBjsjLQychK9gnbf",
                    table_id="tblQGVfmglJgZuBf",
                    records=[{"fields": item.to_feishu_record(fields={"同步任务号": task_id})["fields"]} for item in item_list],
                )

                _update_list = []
                result_list = result.get("data", {}).get("records", [])
                for record, item in zip(result_list, item_list):
                    item.feishu_record_id = record["record_id"]
                    item.is_add_to_feishu = True
                    item.is_update_to_feishu = True
                    _update_list.append(item)
                
                if _update_list:
                    await Follow.bulk_update(_update_list, fields=['feishu_record_id', 'is_add_to_feishu', 'is_update_to_feishu'])
                
                logger.info(f'追加 {len(_update_list)} 条记录到飞书')
                add_list.extend(_update_list)
        
        update_list = []
        # 需要更新的记录
        # follow_list = await Follow.filter(is_update_to_feishu=False, feishu_record_id__isnull=False)
        # if follow_list:
        #     for item_list in split_generator(follow_list, 100):
        #         await create_feishu_records(
        #             get_feishu_client,
        #             app_token="JTqnbdjb7aEMm3srrLfcidYcnxc",
        #             table_id="tblXq8AmG22uK5n1",
        #             records=item_list,
        #         )

        return update_list, add_list
    
    async def set_read(self, id: str):
        await Msg.filter(id=id).update(is_read=True, read_at=datetime.now())

msg_controller = MsgController()

