import bisect
import re
from collections import defaultdict
from typing import Optional, Tuple

IDENTIFIER_RE = re.compile(r"(?<!%)(?:%(\w+)\b|%{(\w+)})")


def fill_template(template_str: str) -> Tuple[Optional[str], str]:
    lines = template_str.splitlines()

    identifier_contexts = defaultdict(list)

    for i, line in enumerate(lines):
        for match in re.finditer(IDENTIFIER_RE, line):
            name = match[1] or match[2]
            for j in range(max(0, i - 2), min(len(lines) - 1, i + 2)):
                ctx = identifier_contexts[name]
                idx = bisect.bisect_left(ctx, j)
                if idx >= len(ctx) or ctx[idx] != j:
                    ctx.insert(idx, j)

    replacements = {}
    for identifier, ctx in identifier_contexts.items():

        def colorize(match):
            name = match[1] or match[2]
            if name == identifier:
                return f"\x1b[31m%{match[1] or match[2]}\x1b[0m"
            else:
                return match[0]

        prev = 0
        printed = 0

        for line_idx in ctx:
            print(re.sub(IDENTIFIER_RE, colorize, lines[line_idx]))
            printed += 1
            if prev and line_idx - prev > 1:
                print("\x1b[1m---\x1b[0m")
                printed += 1
            prev = line_idx

        replacements[identifier] = input("\x1b[1m => " + identifier + ":\x1b[0m ")
        printed += 1

        print(f"\r\x1b[{printed}F\x1b[0J", end="")

    def replace(match):
        return replacements[match[1] or match[2]]

    return replacements.get("name"), re.sub(IDENTIFIER_RE, replace, template_str).replace("%%","%")