from __future__ import annotations

import os
import re
import uuid
from typing import Any

import isort

ENABLE_DEMO_HACKS = os.getenv("ENABLE_DEMO_HACKS", "").lower() in ("1", "true", "yes")


def safe_isort(code: str, **kwargs: Any) -> str:
    """Wrap isort.code to returns the original code if isort fails.

    Args:
        code (str): The Python source code to sort imports for.
        **kwargs: Any additional keyword arguments accepted by isort.code.

    Returns:
        str: The sorted code, or the original code if an exception is raised.

    """
    try:
        return isort.code(code, **kwargs)
    except Exception:  # noqa: BLE001
        return code


def parse_python_version(version: str | None) -> tuple[int, int, int]:
    if not version:
        raise ValueError("Python version is required")
    assert len(version) < 30, "Invalid version format"
    split_version = version.split(".")
    if len(split_version) != 3:
        raise ValueError("Invalid version format")
    patch_str = re.match(r"\d+", split_version[2])
    if not patch_str:
        raise ValueError("Invalid patch version")
    major, minor, patch = int(split_version[0]), int(split_version[1]), int(patch_str.group())
    assert major == 3, "Only Python 3 is supported"
    assert minor >= 9, "Only Python 3.9 and above is supported"
    assert minor <= 15, "Unsupported Python version"
    assert patch >= 0, "Only Python 3.9 and above is supported"
    assert patch < 100, "Invalid version format"

    return (major, minor, patch)


def normalize_trace_id(trace_id: str) -> str | None:
    """Strip EXP0/EXP1 suffixes and return a valid UUID string, or None if invalid."""
    if trace_id[-4:] in ["EXP0", "EXP1"]:
        trace_id = trace_id[:-4] + "0000"
    try:
        uuid_obj = uuid.UUID(trace_id, version=4)
        if str(uuid_obj) != trace_id:
            return None
        return trace_id
    except (ValueError, AttributeError):
        return None


def validate_trace_id(trace_id: str) -> bool:
    return normalize_trace_id(trace_id) is not None


CODEFLASH_EMPLOYEE_GITHUB_IDS = {
    "github|1271289",
    "github|10488227",
    "github|64513301",
    "github|106575910",
    "github|206515457",
    "github|4725571",
    "github|235426847",
}


def is_codeflash_employee(user_id: str) -> bool:
    return user_id in CODEFLASH_EMPLOYEE_GITHUB_IDS


def should_hack_for_demo(source_code: str) -> bool:
    if not ENABLE_DEMO_HACKS:
        return False
    return bool("def find_common_tags(articles" in source_code) or bool("def weighted_sum(series" in source_code)


def should_hack_for_demo_java(source_code: str) -> bool:
    if not ENABLE_DEMO_HACKS:
        return False
    if "byte[] readFile(File" in source_code and "FileInputStream" in source_code:
        return True
    if "class Host" in source_code and "this.name.equals(other.name)" in source_code:
        return True
    return False


def is_host_equals_demo(source_code: str) -> bool:
    if not ENABLE_DEMO_HACKS:
        return False
    return "class Host" in source_code and "this.name.equals(other.name)" in source_code
