import json_repair
import random
import re
from datetime import datetime
from typing import Dict, List
from loguru import logger

from core.config import max_chunk_page, min_single_chunk_size, max_single_chunk_size


def random_str(l=5):
    return "".join(random.sample("abcdefghijklmnopqrstuvwxyz", l))


def format_now():
    """Return current time string formatted as YYYY-MM-DD HH:MM:SS."""
    return datetime.now().strftime("%Y-%m-%d %H:%M:%S")


# 从url中提取文件名称
def extract_url_file(url, support_formats):
    pattern = "|".join(
        [r"[\u4e00-\u9fa5（）()0-9\w-]+" + format for format in support_formats]
    )
    search_result = re.search(pattern, url)
    if search_result:
        return search_result.group()
    else:
        raise Exception(f"{support_formats} not found in url:{url}")


# 调整单个页面数量
def adjust_single_chunk_size(all_text_len):
    desired_chunk_size = all_text_len // max_chunk_page
    return max(min_single_chunk_size, min(desired_chunk_size, max_single_chunk_size))


# 从JSON字符串提取JSON对象
def extract_json(json_str: str) -> List[Dict]:
    """从字符串中提取 JSON 对象列表。

    优先提取 ```json ... ``` 代码块；若不存在，尝试：
    - 解析全文为 JSON
    - 从普通 ``` ... ``` 代码块解析
    - 从任意包含花括号/方括号的片段尝试解析
    返回解析成功的 JSON 对象列表（数组会被展开）。
    """

    def _try_parse_to_list(candidate: str, out_list: list) -> bool:
        s = (candidate or "").strip()
        if not s:
            return False
        # 清理控制字符
        s = re.sub(r"[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]", "", s)
        try:
            obj = json_repair.loads(s, strict=False)
            if isinstance(obj, list):
                out_list.extend(obj)
            else:
                out_list.append(obj)
            return True
        except Exception as e:
            logger.error(f"JSON解析失败: {e} | 内容片段: {s}")
            return False

    results = []

    # 1. 提取 ```json ... ``` 代码块
    fenced_json_pattern = r"```json([\s\S]*?)```"
    for match in re.findall(fenced_json_pattern, json_str or "", re.DOTALL):
        _try_parse_to_list(match, results)

    if results:
        return results

    # 2. 尝试将全文解析为 JSON
    if _try_parse_to_list(json_str or "", results):
        return results

    # 3. 提取普通 ``` ... ``` 代码块，尝试解析
    fenced_any_pattern = r"```([\s\S]*?)```"
    for match in re.findall(fenced_any_pattern, json_str or "", re.DOTALL):
        if _try_parse_to_list(match, results):
            return results

    # 4. 从包含花括号/方括号的片段尝试解析（启发式，尽力而为）
    bracket_pattern = r"(\{[\s\S]*?\}|\[[\s\S]*?\])"
    for match in re.findall(bracket_pattern, json_str or "", re.DOTALL):
        _try_parse_to_list(match, results)

    return results


def remove_duplicates_by_key(data_list, key):
    # 先按字符串长度从长到短排序
    sorted_list = sorted(data_list, key=lambda x: len(x.get(key, "")), reverse=True)

    result = []
    seen_strings = []

    for item in sorted_list:
        value = item.get(key, "")
        if not any(value in s for s in seen_strings):
            seen_strings.append(value)
            result.append(item)

    return result


def extract_drop_json_part(json_str):
    json_pattern = r"```json([\s\S]*?)```"
    non_json_content = re.sub(json_pattern, "", json_str, re.DOTALL)
    return non_json_content.strip()


def group_chunk_by_len(
    chunk_list: List[Dict], key: str, chunk_len: int
) -> List[List[Dict]]:
    ret_chunk_list = []
    sub_chunk_list = []
    current_acc_len = 0  # 用于记录当前 sub_chunk 的累积长度

    for chunk in chunk_list:
        # 获取当前字典中指定 key 的内容的长度
        # 使用 .get(key, "") 防止 key 不存在导致报错
        content_len = len(chunk.get(key, ""))

        # 判断：如果当前累积长度 + 新内容的长度 > 限制长度
        # 且 sub_chunk_list 不为空（确保即使单个元素超长也能被添加）
        if current_acc_len + content_len > chunk_len and sub_chunk_list:
            # 将当前组加入结果集
            ret_chunk_list.append(sub_chunk_list)
            # 重置当前组和计数器
            sub_chunk_list = []
            current_acc_len = 0

        # 将当前 chunk 加入子列表
        sub_chunk_list.append(chunk)
        current_acc_len += content_len

    # 循环结束后，如果 sub_chunk_list 还有剩余内容，需要加入结果集
    if sub_chunk_list:
        ret_chunk_list.append(sub_chunk_list)

    return ret_chunk_list


if __name__ == "__main__":
    json_str = '```json{"segment_id": "seg-001"}```'
    print(extract_json(json_str))

    url = "/api/common/file/read/今麦郎合同审核.docx?token=eyJhbGciOiJ.kpXVCJ9.1xfdsa"
    print(extract_url_file(url, [".docx", ".doc", ".wps"]))
    pass
