import re


def parse_js_string(s):
    """Parse a JS double-quoted string with escape sequences."""
    result = []
    i = 0
    while i < len(s):
        if s[i] == '\\' and i + 1 < len(s):
            nxt = s[i + 1]
            if nxt == '"':
                result.append('"')
                i += 2
            elif nxt == '\\':
                result.append('\\')
                i += 2
            elif nxt == 'n':
                result.append('\n')
                i += 2
            elif nxt == 't':
                result.append('\t')
                i += 2
            elif nxt == 'b':
                result.append('\b')
                i += 2
            elif nxt == 'f':
                result.append('\f')
                i += 2
            elif nxt == '/':
                result.append('/')
                i += 2
            else:
                result.append('\\' + nxt)
                i += 2
        else:
            result.append(s[i])
            i += 1
    return ''.join(result)


def parse_cards_js(path):
    content = open(path).read()
    m = re.search(r"window\.CARDS\s*=\s*(\[.*\]);", content, re.DOTALL)
    if not m:
        raise ValueError("Cannot find CARDS array")
    js_array = m.group(1)

    # Tokenize: find each { ... } object
    # We walk through the array character by character, tracking brace depth
    cards = []
    i = 0
    n = len(js_array)
    while i < n:
        # Skip whitespace and commas
        while i < n and js_array[i] in ' \t\n\r,':
            i += 1
        if i >= n or js_array[i] != '{':
            break
        # Find the matching closing brace
        depth = 0
        start = i
        in_string = False
        escape = False
        while i < n:
            c = js_array[i]
            if escape:
                escape = False
                i += 1
                continue
            if c == '\\' and in_string:
                escape = True
                i += 1
                continue
            if c == '"':
                in_string = not in_string
            elif not in_string:
                if c == '{':
                    depth += 1
                elif c == '}':
                    depth -= 1
                    if depth == 0:
                        i += 1
                        break
            i += 1
        obj_text = js_array[start:i]

        # Extract d, q, a from the object
        def extract_field(obj, field):
            # Find "field:" followed by a string
            pat = re.compile(
                r'\b' + field + r'\s*:\s*"((?:[^"\\]|\\.)*)"',
                re.DOTALL,
            )
            m2 = pat.search(obj)
            if m2:
                return parse_js_string(m2.group(1))
            return None

        d = extract_field(obj_text, 'd')
        q = extract_field(obj_text, 'q')
        a = extract_field(obj_text, 'a')
        if d and q and a:
            cards.append({"deck": d, "question": q, "answer": a})
        i += 1

    return cards


cards = parse_cards_js("/Users/brians/Documents/AveryArt/Gallery Drill/cards.js")
print(f"Total cards: {len(cards)}")
cats = {}
for c in cards:
    cats[c["deck"]] = cats.get(c["deck"], 0) + 1
for cat, n in sorted(cats.items()):
    print(f"  {cat:<20} {n} cards")
print()
seen = set()
for c in cards:
    if c["deck"] not in seen:
        seen.add(c["deck"])
        print(f"  [{c['deck']}] Q: {c['question'][:80]}...")
print()
print("Sample answer (Banksy):")
for c in cards:
    if c["deck"] == "Street & Pop" and "Banksy" in c["question"] and "what is the buyer" in c["question"]:
        print(f"  A: {c['answer'][:200]}")
        break
