import re

def clean(input_str: str) -> str:
    if not input_str or not input_str.strip():
        return ""
    
    text = input_str

    # 1. Extract Markdown Code Block
    def text_with_json(s):
        return '{' in s or '[' in s

    # Priority A: Complete blocks
    # re.DOTALL makes . match newlines
    complete_block_pattern = re.compile(r'```(?:json)?(.*?)```', re.IGNORECASE | re.DOTALL)
    candidates = complete_block_pattern.findall(text)
    
    best_candidate = None
    for candidate in candidates:
        if text_with_json(candidate):
            best_candidate = candidate
            break
    
    if best_candidate:
        text = best_candidate
    else:
        # Priority B: Unclosed block at the end
        unclosed_block_pattern = re.compile(r'```(?:json)?(.*)$', re.IGNORECASE | re.DOTALL)
        match = unclosed_block_pattern.search(text)
        if match and text_with_json(match.group(1)):
            text = match.group(1)

    # 2. Strip Comments
    text = strip_comments(text)

    # 3. Find Start of JSON
    first_brace = text.find('{')
    first_bracket = text.find('[')

    if first_brace == -1 and first_bracket == -1:
        return text.strip()

    # Determine start index
    if first_brace != -1 and (first_bracket == -1 or first_brace < first_bracket):
        start = first_brace
    else:
        start = first_bracket
        
    candidate = text[start:]

    # 4. Remove Conversational Garbage
    candidate = remove_conversational_garbage(candidate)

    # 5. Find End (Balanced) & Handle Truncation
    balanced = get_balanced_substring(candidate)
    candidate = balanced['text']

    # 6. Heuristic Repairs
    
    # Fix Python constants
    candidate = re.sub(r'\bNone\b', 'null', candidate)
    candidate = re.sub(r'\bTrue\b', 'true', candidate)
    candidate = re.sub(r'\bFalse\b', 'false', candidate)

    # Fix Unquoted Keys: { key: -> { "key":
    candidate = re.sub(r'([{,]\s*)([a-zA-Z0-9_$\-]+)(\s*:)', r'\1"\2"\3', candidate)
    
    # Fix Single Quoted Keys: { 'key': -> { "key":
    candidate = re.sub(r"([{,]\s*)'([a-zA-Z0-9_$\-]+)'(\s*:)", r'\1"\2"\3', candidate)

    # Fix Single Quoted Values: : 'value' -> : "value"
    def replace_single_quotes(match):
        content = match.group(1)
        # escape double quotes inside, unescape single quotes
        content = content.replace("\\'", "'").replace('"', '\\"')
        return f': "{content}"'
    
    candidate = re.sub(r":\s*'((?:[^'\\]|\\.)*)'", replace_single_quotes, candidate)

    # Fix Trailing Commas: [1, 2, ] -> [1, 2 ]
    candidate = re.sub(r',(\s*[}\]])', r'\1', candidate)

    # Fix missing value: "key": } -> "key": null }
    candidate = re.sub(r':\s*([}\]])', r': null\1', candidate)

    return candidate

def strip_comments(text: str) -> str:
    result = []
    i = 0
    length = len(text)
    in_string = False
    quote_char = ''
    escape = False
    
    while i < length:
        char = text[i]
        next_char = text[i+1] if i + 1 < length else ''
        
        if in_string:
            if char == '\\' and not escape:
                escape = True
            elif char == quote_char and not escape:
                in_string = False
            else:
                escape = False
            result.append(char)
            i += 1
            continue
            
        if char == '"' or char == "'":
            in_string = True
            quote_char = char
            result.append(char)
            i += 1
            continue
            
        # Block Comment /* ... */
        if char == '/' and next_char == '*':
            i += 2
            while i < length and not (text[i] == '*' and (text[i+1] if i+1 < length else '') == '/'):
                i += 1
            i += 2 # Skip closing */
            continue
            
        # Line Comment // ...
        if char == '/' and next_char == '/':
            i += 2
            while i < length and text[i] != '\n':
                i += 1
            continue
            
        result.append(char)
        i += 1
        
    return "".join(result)

def remove_conversational_garbage(text: str) -> str:
    i = 0
    length = len(text)
    in_string = False
    quote_char = ''
    escape = False
    
    while i < length:
        char = text[i]
        
        if in_string:
            if char == '\\' and not escape:
                escape = True
            elif char == quote_char and not escape:
                in_string = False
            else:
                escape = False
            i += 1
            continue
            
        if char == '"' or char == "'":
            in_string = True
            quote_char = char
            i += 1
            continue
            
        # Check for Identifier start
        if re.match(r'[a-zA-Z_$]', char):
            # Scientific notation check
            if (char == 'e' or char == 'E') and i > 0 and re.match(r'[0-9]', text[i-1]):
                i += 1
                continue
                
            # Read full word
            j = i
            word = ""
            while j < length and re.match(r'[a-zA-Z0-9_$]', text[j]):
                word += text[j]
                j += 1
                
            is_literal = re.match(r'^(true|false|null|none|nan|infinity|undefined)$', word, re.IGNORECASE)
            
            if not is_literal:
                # Check if it's a key (must be followed by colon)
                k = j
                while k < length and text[k].isspace():
                    k += 1
                
                if k < length and text[k] == ':':
                    pass # It's a key
                else:
                    # It's garbage text, truncate here
                    return text[:i]
            
            i = j
            continue
        
        i += 1
        
    return text

def get_balanced_substring(text: str) -> dict:
    stack = []
    in_string = False
    quote_char = ''
    escape = False
    end_index = -1
    length = len(text)
    
    for i, char in enumerate(text):
        if in_string:
            if char == '\\' and not escape:
                escape = True
            elif char == quote_char and not escape:
                in_string = False
            else:
                escape = False
            continue
            
        if char == '"' or char == "'":
            in_string = True
            quote_char = char
            continue
            
        if char == '{':
            stack.append('}')
        elif char == '[':
            stack.append(']')
        elif char == '}' or char == ']':
            if stack:
                expected = stack[-1]
                if char == expected:
                    stack.pop()
                    if not stack:
                        end_index = i
                        break
            else:
                # Found closer with no opener
                if end_index == -1:
                    end_index = i - 1
                break
                
    # Case 1: Clean finish
    if not stack and end_index != -1:
        return {'text': text[:end_index+1], 'is_truncated': False}
        
    # Case 2: Truncated
    corrected = text
    while stack:
        corrected += stack.pop()
        
    return {'text': corrected, 'is_truncated': True}