import hashlib
import os
import re
import time

from sweepai.config.server import PROGRESS_BASE_URL

UPDATES_MESSAGE = f"""\
<details>
<summary><b>🎉 Latest improvements to Sweep:</b></summary>
<ul>
<li>New <a href="{PROGRESS_BASE_URL}">dashboard</a> launched for real-time tracking of Sweep issues, covering all stages from search to coding.</li>
<li>Integration of OpenAI's latest Assistant API for more efficient and reliable code planning and editing, improving speed by 3x.</li>
<li>Use the <a href="https://marketplace.visualstudio.com/items?itemName=GitHub.vscode-pull-request-github">GitHub issues extension</a> for creating Sweep issues directly from your editor.</li>
</ul>
</details>
"""

DEFAULT_BOT_SUFFIX = "\n\n*This is an automated message generated by [Sweep AI](https://sweep.dev).*"
BOT_SUFFIX = os.environ.get("BOT_SUFFIX", DEFAULT_BOT_SUFFIX).replace("\\n", "\n")

if BOT_SUFFIX != DEFAULT_BOT_SUFFIX:
    print(f"Using custom bot suffix: {BOT_SUFFIX}")

FASTER_MODEL_MESSAGE = """\
You ran out of the free tier GPT-4 tickets! We no longer support running Sweep with GPT-3.5 as it is too unreliable. Here are your options:
- You can get a free trial of Sweep Pro to get unlimited GPT-4 tickets [here](https://buy.stripe.com/00g5npeT71H2gzCfZ8) or purchase a individual GPT-4 tickets [here](https://buy.stripe.com/00g3fh7qF85q0AE14d).
- You can self-host Sweep with your own GPT-4 API key. You can find instructions [here](https://docs.sweep.dev/deployment).
- You can book a chat with us to discuss your use case and get additional free GPT-4 tickets [here](https://calendly.com/d/2n5-3qf-9xy/user-interview).
"""

sep = "\n---\n"
bot_suffix_starring = ""
bot_suffix = (
    f"\n{sep}\n{UPDATES_MESSAGE}\n\n💡 To recreate the pull request edit the issue"
    " title or description."
)
discord_suffix = (
    "\n<sup>Something wrong? [Let us know](https://discord.gg/sweep).</sup>"
)

stars_suffix = ""

collapsible_template = """
<details {opened}>
<summary>{summary}</summary>

{body}
</details>
"""

checkbox_template = "- [{check}] {filename}\n{instructions}\n"

num_of_snippets_to_query = 30
total_number_of_snippet_tokens = 15_000
num_full_files = 2


def ordinal(n):
    return str(n) + (
        "th" if 4 <= n <= 20 else {1: "st", 2: "nd", 3: "rd"}.get(n % 10, "th")
    )


def format_sandbox_success(success):
    return "✓" if success else "❌ (`Sandbox Failed`)"


def create_collapsible(summary: str, body: str, opened: bool = False):
    return collapsible_template.format(
        summary=summary, body=body, opened="open" if opened else ""
    )


def inline_code(text: str):
    return f"<code>{text}</code>" if text else ""


def code_block(text: str):
    return f"<pre>{text}</pre>" if text else ""


def blockquote(text: str):
    text = text.replace("\n•", "<br/>•")
    return f"<blockquote>{text}\n</blockquote>" if text else ""


def create_checkbox(title: str, body: str, checked: bool = False):
    return checkbox_template.format(
        check="X" if checked else " ", filename=title, instructions=body
    )


def strip_sweep(text: str):
    return (
        re.sub(
            r"^[Ss]weep\s?(\([Ss]low\))?(\([Mm]ap\))?(\([Ff]ast\))?\s?:", "", text
        ).lstrip(),
        re.search(r"^[Ss]weep\s?\([Ss]low\)", text) is not None,
        re.search(r"^[Ss]weep\s?\([Mm]ap\)", text) is not None,
        re.search(r"^[Ss]weep\s?\([Ss]ubissues?\)", text) is not None,
        re.search(r"^[Ss]weep\s?\([Ss]andbox?\)", text) is not None,
        re.search(r"^[Ss]weep\s?\([Ff]ast\)", text) is not None,
        re.search(r"^[Ss]weep\s?\([Ll]int\)", text) is not None,
    )


def clean_logs(logs: str):
    cleaned_logs = re.sub(r"\x1b\[.*?[@-~]", "", logs.replace("```", "\`\`\`"))
    cleaned_logs = re.sub("\n{2,}", "\n", cleaned_logs)
    cleaned_logs = re.sub("\r{2,}", "\n", cleaned_logs)
    cleaned_logs = cleaned_logs.strip("\n")
    cleaned_logs = cleaned_logs or "(nothing was outputted)"
    return cleaned_logs


def extract_lines(text: str, start: int, end: int):
    lines = text.splitlines(keepends=True)
    return "\n".join(lines[max(0, start) : min(len(lines), end)])


def add_line_numbers(text: str, start: int = 0):
    lines = text.splitlines(keepends=True)
    return "".join(f"{start + i} | {line}" for i, line in enumerate(lines))


def to_branch_name(s, max_length=40):
    branch_name = s.strip().lower().replace(" ", "_")
    branch_name = re.sub(r"[^a-z0-9_]", "", branch_name)
    return branch_name[:max_length]


def get_hash():
    return hashlib.sha256(str(time.time()).encode()).hexdigest()[:10]

# used for getting all indices of a substring match
def get_all_indices_of_substring(content: str, substring: str):
    start = 0
    indices = []
    while True:
        index = content.find(substring, start)
        if index == -1:  # No more occurrences found
            break
        indices.append(index)
        start = index + 1  # Move past the last found occurrence
    return indices