# 1 日志不打在server中 不打在工具中, 只打在core 中

import math
import asyncio
from pro_craft import AsyncIntel
from pro_craft.utils import create_async_session
from digital_life.utils import memoryCards2str
from digital_life.models import MemoryCardGenerate,MemoryCardGenerateEasy, MemoryCard2, MemoryCard, MemoryCardScore, MemoryCards, Document, Chapter, MemoryCardsGenerate
from digital_life import super_log
from datetime import datetime
from typing import Dict, Any, Optional, List
from pydantic import BaseModel, Field, model_validator, field_validator, RootModel
import re

class MemoryCardManager:
    def __init__(self,inference_save_case = False,model_name = "doubao-1-5-pro-256k-250115"):
        self.inters = AsyncIntel(model_name = model_name)
        self.inference_save_case = inference_save_case

    @staticmethod
    def get_score_overall(
        S: list[int], total_score: int = 0, epsilon: float = 0.001, K: float = 0.8
    ) -> float:
        """
        计算 y = sqrt(1/600 * x) 的值。
        计算人生总进度
        """
        x = sum(S)
        
        S_r = [math.sqrt((1/101) * i)/6 for i in S]
        return sum(S_r)

        # return math.sqrt((1/601) * x)  * 100

    @staticmethod
    def get_score(
        S: list[int], total_score: int = 0, epsilon: float = 0.001, K: float = 0.01
    ) -> float:
        # 人生主题分值计算
        # 一个根据 列表分数 计算总分数的方法 如[1,4,5,7,1,5] 其中元素是 1-10 的整数

        # 一个非常小的正数，确保0分也有微弱贡献，100分也不是完美1
        # 调整系数，0 < K <= 1。K越大，总分增长越快。

        for score in S:
            # 1. 标准化每个分数到 (0, 1) 区间
            normalized_score = (score + epsilon) / (10 + epsilon)

            # 2. 更新总分
            # 每次增加的是“距离满分的剩余空间”的一个比例
            total_score = total_score + (100 - total_score) * normalized_score * K

            # 确保不会因为浮点数精度问题略微超过100，虽然理论上不会
            if total_score >= 100 - 1e-9:  # 留一点点余地，避免浮点数误差导致判断为100
                total_score = 100 - 1e-9  # 强制设置一个非常接近100但不等于100的值
                break  # 如果已经非常接近100，可以提前终止

        return total_score

    async def ascore_from_memory_card(self, memory_cards: list[str]) -> list[int]:
        # 正式运行 0088
        tasks = []
        for memory_card in memory_cards:
            tasks.append(
                self.inters.intellect_format(
                    input_data=memory_card,
                    prompt_id = "memorycard-score",
                    version = None,
                    inference_save_case=self.inference_save_case,
                    OutputFormat = MemoryCardScore,
                )
            )
        result = await asyncio.gather(*tasks, return_exceptions=False)
        return result

    async def amemory_card_merge(self, memory_cards: list[str]):
        # 0089
        memoryCards_str, memoryCards_time_str = memoryCards2str(memory_cards)
        result_1 = await self.inters.intellect_format(
            input_data=memoryCards_str + "\n 各记忆卡片的时间" + memoryCards_time_str,
            prompt_id = "memorycard-merge",
            version = None,
            inference_save_case=self.inference_save_case,
            OutputFormat = MemoryCard2,
        )
        return result_1

    async def amemory_card_polish(self, memory_card: dict) -> dict:
        # 0090
        result = await self.inters.intellect_format(
            input_data="\n记忆卡片标题: "+ memory_card["title"]+ "\n记忆卡片内容: " + memory_card["content"] + "\n记忆卡片发生时间: " + memory_card["time"],
            prompt_id = "memorycard-polish",
            version = None,
            inference_save_case=self.inference_save_case,
            OutputFormat = MemoryCard,
        )
        result.update({"time": ""})
        return result


    async def agenerate_memory_card(self, chat_history_str: str, weight: int = 1000):
        """
        0093 聊天历史生成记忆卡片-memory_card_system_prompt
        0094 聊天历史生成记忆卡片-time_prompt
        """
        number_ = len(chat_history_str) // weight + 1
        result_dict = await self.inters.intellect_format(
            input_data = f"建议输出卡片数量:  {number_} 个记忆卡片" + chat_history_str,
            prompt_id = "memorycard-generate-content",
            version = None,
            inference_save_case=self.inference_save_case,
            OutputFormat = Document,
            ExtraFormats=[Chapter],
        )
        chapters = result_dict["chapters"]


        class MemoryCardGenerate2(BaseModel):
            title: str = Field(..., description="标题",min_length=1, max_length=30)
            content: str = Field(..., description="内容",min_length=1,max_length=1000)
            time: str = Field(..., description="日期格式,YYYY年MM月DD日,其中YYYY可以是4位数字或4个下划线,MM可以是2位数字或2个--,DD可以是2位数字或2个--。年龄范围 输出对应的文字描述, 比如:而立, 不惑")
            score: int = Field(..., description="卡片得分", ge=0, le=10)
            tag: str = Field(..., description="标签1",max_length=4)
            topic: int = Field(..., description="主题1-5",ge=0, le=5)

            @field_validator('time')
            @classmethod
            def validate_time_format(cls, v: str) -> str:
                combined_regex = r"^(?:(\d{4}|-{4}|-{2})年(\d{2}|-{2})月(\d{2}|-{2})日)"
                match = re.match(combined_regex, v)
                if match:
                    return v
                elif v in ["稚龄","少年","弱冠","而立","不惑","知天命","耳顺","古稀","耄耋","鲐背","期颐"]:
                    return v
                else:
                    raise ValueError("时间无效")
        
        class TimeCheck(BaseModel):
            time: str = Field(...,description="")
            @field_validator('time')
            @classmethod
            def validate_time_format(cls, v: str) -> str:
                combined_regex = r"^(?:(\d{4}|-{4}|-{2})年(\d{2}|-{2})月(\d{2}|-{2})日)"
                match = re.match(combined_regex, v)
                if match:
                    return v
                elif v in ["稚龄","少年","弱冠","而立","不惑","知天命","耳顺","古稀","耄耋","鲐背","期颐"]:
                    return v
                else:
                    raise ValueError("时间无效")


        time_dicts = await self.inters.intellect_formats(
            input_datas=[f"# chat_history: {chat_history_str} # chapter:" + chapter.get("content") + f"当前时间为{datetime.now()}" for chapter in chapters],
            prompt_id = "memorycard-format",
            version = None,
            inference_save_case=self.inference_save_case,
            OutputFormat = MemoryCardGenerate2,
        )

        doc = {"稚龄":"0到10岁",
        "少年":"11到20岁",
        "弱冠":"21到30岁",
        "而立":"31到40岁",
        "不惑":"41到50岁",
        "知天命":"51到60岁",
        "耳顺":"61到70岁",
        "古稀":"71到80岁",
        "耄耋":"81到90岁",
        "鲐背":"91到100岁",
        "期颐":"101到110岁"}

        time_dicts_time = [time_dict.get('time') for time_dict in time_dicts]
        for i,time_dict in enumerate(time_dicts):
            llm_result_time = time_dicts_time[i]
            try:
                TimeCheck(time = llm_result_time)
            except Exception as e:
                super_log(f"Error{e}",'error')
                llm_result_time = "----年--月--日"

            if "月" in llm_result_time:
                # 一定是 --一年--月--日
                time_ = llm_result_time.replace('-','1')
                try:
                    date_obj = datetime.strptime(time_, "%Y年%m月%d日")
                    target_date = datetime.now()
                    if date_obj > target_date:
                        llm_result_time = "----年--月--日"

                except Exception as e:
                    llm_result_time = "----年--月--日"

            xx = doc.get(llm_result_time,llm_result_time)
            time_dict.update({"time":xx})

        super_log(time_dicts,"generate_memory_card-time_dicts")
        if not len(time_dicts) == len([f"# chat_history: {chat_history_str} # chapter:" + chapter.get("content") for chapter in chapters]):
            chapters = chapters[:1]
        for i,chapter in enumerate(chapters):
            chapter.update(time_dicts[i])
        
        for chapter in chapters:
            try:
                MemoryCardsGenerate(memory_cards=[chapter])
            except Exception as e:
                super_log(f"{e}",'agenerate_memory_card Error')
                chapter.update({"time":"----年--月--日"})
                
        return chapters







    async def agenerate_memory_card_by_text(self, chat_history_str: str, weight: int = 1000):
        return await self.agenerate_memory_card(chat_history_str = chat_history_str,weight = weight)
    




        

