import json, re, os

with open('C:/allgifted/mathapi11v2/_work_barmodels/audit_final/af_slice.json', 'r', encoding='utf-8') as f:
    data = json.load(f)

# --- helper: extract the correct answer(s) from the data ---
def correct_answer(entry):
    t = entry['type']
    answers = entry['answers']
    ci = entry['correct_index']
    if t == 1:  # MCQ
        if ci is not None and 0 <= ci < len(answers):
            a = answers[ci]
            return a.strip() if a else ''
        # if ci is None for MCQ, try first non-None
        for a in answers:
            if a is not None:
                return a.strip()
        return ''
    else:  # FIB type 2
        a = answers[0] if answers[0] is not None else ''
        return str(a).strip()

# --- helper: check solution quality ---
def audit_solution(entry):
    sol = entry.get('solution', '').strip()
    qid = entry['id']
    expected = correct_answer(entry)

    issues = []

    # 1. Empty solution
    if not sol or len(sol) < 10:
        issues.append('empty or too-short solution')
        return 'NEEDS_REVISION', issues

    # 2. Check for gibberish/placeholder patterns
    gibberish_patterns = ['lorem ipsum', 'TODO', '[TODO]', '[PLACEHOLDER]',
                          'bar model here', 'insert solution', 'TBD', '???']
    for gp in gibberish_patterns:
        if gp.lower() in sol.lower():
            issues.append('contains placeholder: ' + gp)
            break

    # 3. Check if the answer appears in the solution (loose match)
    sol_clean = sol.lower()
    if entry['type'] == 1:
        # For MCQ, check for the option text in solution
        expected_lower = expected.lower()
        expected_lower = expected_lower.replace('\\\\', '').replace('\\dfrac', 'frac').strip()
        expected_lower = expected_lower.replace('\\frac', 'frac').replace('\\', '').strip()
        if expected_lower and expected_lower not in sol_clean:
            # Try to find just the key word from the answer
            # e.g., "Soccer Ball" → check if "soccer" is in the solution
            words = expected_lower.split()
            found = any(w in sol_clean for w in words if len(w) > 2)
            if not found:
                issues.append('expected MCQ answer text not found in solution')
    else:
        # FIB - check numeric answer
        expected_num = expected.strip()
        if expected_num:
            parts = [p.strip() for p in expected_num.split(',')]
            for p in parts:
                if p and p not in sol_clean:
                    issues.append('expected answer "' + p + '" not found in solution')
                    break

    # 4. Check for obvious math errors (simple arithmetic)
    math_exprs = re.findall(r'(\d+\.?\d*)\s*([+\-])\s*(\d+\.?\d*)\s*=\s*(\d+\.?\d*)', sol)
    for m_left, op, m_right, m_result in math_exprs:
        left = float(m_left)
        right = float(m_right)
        result = float(m_result)
        if op == '+':
            actual = left + right
        else:
            actual = left - right
        if abs(actual - result) > 0.01:
            issues.append('math error: ' + m_left + op + m_right + '=' + m_result + ' should be ' + str(actual))

    # Check multiplication
    math_exprs_x = re.findall(r'(\d+\.?\d*)\s*[x\xd7]\s*(\d+\.?\d*)\s*=\s*(\d+\.?\d*)', sol)
    for a, b, c in math_exprs_x:
        if abs(float(a) * float(b) - float(c)) > 0.01:
            issues.append('math error: ' + a + 'x' + b + '=' + c + ' should be ' + str(float(a)*float(b)))

    # Check division
    math_exprs_div = re.findall(r'(\d+\.?\d*)\s*[\xf7/]\s*(\d+\.?\d*)\s*=\s*(\d+\.?\d*)', sol)
    for a, b, c in math_exprs_div:
        if float(b) != 0 and abs(float(a) / float(b) - float(c)) > 0.01:
            issues.append('math error: ' + a + '/ ' + b + '=' + c + ' should be ' + str(float(a)/float(b)))

    if issues:
        return 'NEEDS_REVISION', issues
    else:
        return 'GOOD', []

# --- Main audit ---
good = []
needs_revision = {}

for i, entry in enumerate(data):
    qid = entry['id']
    verdict, issues = audit_solution(entry)
    if verdict == 'GOOD':
        good.append(qid)
    else:
        needs_revision[str(qid)] = '; '.join(issues)

print('GOOD: ' + str(len(good)))
print('NEEDS_REVISION: ' + str(len(needs_revision)))
print()

for qid, reason in sorted(needs_revision.items(), key=lambda x: int(x[0])):
    print('  Q' + qid + ': ' + reason)

out = {"good": good, "needs_revision": needs_revision}
with open('C:/allgifted/mathapi11v2/_work_barmodels/audit_final/af_8040_8240.json', 'w', encoding='utf-8') as f:
    json.dump(out, f, ensure_ascii=False, indent=2)
print('\nWrote to af_8040_8240.json')
