import re
from typing import List

import tiktoken


def count_tokens(string: str, encoding_name: str = "cl100k_base") -> int:
    """Return numbers of token"""
    # https://stackoverflow.com/questions/75804599/openai-api-how-do-i-count-tokens-before-i-send-an-api-request
    # https://github.com/openai/tiktoken
    encoding = tiktoken.get_encoding(encoding_name)
    num_tokens = len(encoding.encode(string))
    return num_tokens


def split_string_into_slices(s: str, slice_size: int) -> List[str]:
    return [s[i : i + slice_size] for i in range(0, len(s), slice_size)]


def limit_tokens(content: str, max_token: int) -> str:
    slice_size = 10
    split_ = split_string_into_slices(content, slice_size)
    last_string = ""
    for sp in split_:
        new_token = count_tokens(last_string + sp)
        if new_token < max_token:
            last_string += sp
        else:
            break
    return last_string


def escape_json_string_values(json_string: str) -> str:
    """escape \\n and \\t in json string
    # credit: chatgpt
    :param json_string:
    :return:
    """

    def escape_special_chars(match):
        inner_str = match.group(1)
        # Escape backslashes first to avoid double escaping
        inner_str = inner_str.replace("\\", "\\\\")
        inner_str = inner_str.replace("\n", "\\n").replace("\t", "\\t")
        return f'"{inner_str}"'

        # Use regex to find all string values in JSON and apply escaping

    escaped_json_string = re.sub(
        r'"([^"\\]*(?:\\.[^"\\]*)*)"', escape_special_chars, json_string
    )

    return escaped_json_string
