import subprocess, json, urllib.request

def sh(c): return subprocess.run(c, shell=True, capture_output=True, text=True).stdout.strip()
def sql(q): return sh("mysql -u root zc_safeguarding -N -e \"%s\"" % q)

ok = fail = 0
def check(name, cond, detail=''):
    global ok, fail
    if cond: ok += 1; print('PASS', name)
    else: fail += 1; print('FAIL', name, detail)

# Two triage-capable staff (one with a phone, one without), plus one user
# WITHOUT cases.triage who must never be notified.
sql("""
INSERT INTO users (uuid, full_name, email, phone, password_hash, status, must_change_password, created_at, updated_at)
VALUES
  (UUID(), 'Officer WithPhone', 'officer.phone@example.com', '263771230000', 'x', 'active', 0, NOW(), NOW()),
  (UUID(), 'Officer NoPhone', 'officer.nophone@example.com', NULL, 'x', 'active', 0, NOW(), NOW()),
  (UUID(), 'Reviewer OnlyView', 'reviewer@example.com', '263771239999', 'x', 'active', 0, NOW(), NOW());
""")
officer1 = sql("SELECT id FROM users WHERE email='officer.phone@example.com'")
officer2 = sql("SELECT id FROM users WHERE email='officer.nophone@example.com'")
reviewer = sql("SELECT id FROM users WHERE email='reviewer@example.com'")
officer_role = sql("SELECT id FROM roles WHERE name='Safeguarding Officer'")
reviewer_role = sql("SELECT id FROM roles WHERE name='Safeguarding Reviewer'")
sql(f"INSERT INTO user_roles (user_id, role_id, assigned_at) VALUES ({officer1},{officer_role},NOW()),({officer2},{officer_role},NOW()),({reviewer},{reviewer_role},NOW())")

def outbox_tail(path, before):
    lines = open(path).read().splitlines() if __import__('os').path.exists(path) else []
    return [json.loads(l) for l in lines[before:]]
def outbox_len(path):
    import os
    return len(open(path).read().splitlines()) if os.path.exists(path) else 0

EMAIL_OUT = '/home/claude/zc/zc/storage/logs/email-outbox.log'
WA_OUT = '/home/claude/zc/zc/storage/logs/whatsapp-outbox.log'

print('--- urgent CONFIDENTIAL web report triggers notifications ---')
eb, wb = outbox_len(EMAIL_OUT), outbox_len(WA_OUT)
r = json.loads(sh("""curl -s -X POST http://127.0.0.1:8110/api/reporting/submit.php -H 'X-Requested-With: fetch' -H 'Accept: application/json' \
  -F concern_type=Neglect -F affected_who=Player -F incident_date=today -F location=Ground \
  -F description='SENSITIVE DETAILS THAT MUST NEVER APPEAR IN A NOTIFICATION' -F current_risk=yes \
  -F reporter_name=Web -F reporter_email=w@example.com"""))
check('submit succeeded', r.get('success'), r)
case_number = r.get('case_number')
emails = outbox_tail(EMAIL_OUT, eb)
whatsapps = outbox_tail(WA_OUT, wb)
check('exactly 2 emails sent (both triage-capable officers)', len(emails) == 2, emails)
check('email recipients are the two officers, NOT the view-only reviewer',
      {e['to'] for e in emails} == {'officer.phone@example.com', 'officer.nophone@example.com'}, emails)
check('email subject carries the case number', all(case_number in e['subject'] for e in emails), emails)
check('email body has case number + category + risk, no raw description',
      all(case_number in e['body'] and 'Neglect' in e['body'] and 'yes' in e['body'] for e in emails) and
      all('SENSITIVE DETAILS' not in e['body'] for e in emails), emails)
check('exactly 1 WhatsApp alert (only the officer with a phone on file)', len(whatsapps) == 1, whatsapps)
check('WhatsApp alert went to the right number', whatsapps and whatsapps[0]['to'] == '263771230000', whatsapps)
check('WhatsApp body has no raw description either',
      whatsapps and 'SENSITIVE DETAILS' not in whatsapps[0]['body'], whatsapps)

case_id = sql(f"SELECT id FROM safeguarding_cases WHERE case_number='{case_number}'")
rows = sql(f"SELECT channel, status, recipient_user_id FROM notification_deliveries WHERE case_id={case_id} ORDER BY channel, recipient_user_id")
check('notification_deliveries has 3 rows (2 email + 1 whatsapp), all sent',
      len(rows.splitlines()) == 3 and all('\tsent' in r or r.endswith('sent') for r in rows.splitlines()), rows)

print('--- non-urgent report triggers NO notification ---')
eb2, wb2 = outbox_len(EMAIL_OUT), outbox_len(WA_OUT)
r2 = json.loads(sh("""curl -s -X POST http://127.0.0.1:8110/api/reporting/submit.php -H 'X-Requested-With: fetch' -H 'Accept: application/json' \
  -F concern_type=Neglect -F affected_who=Player -F incident_date=today -F location=Ground \
  -F description='not urgent' -F current_risk=no -F reporter_name=Web2 -F reporter_email=w2@example.com"""))
check('non-urgent submit succeeded', r2.get('success'), r2)
check('no new emails for a non-urgent report', outbox_len(EMAIL_OUT) == eb2, (eb2, outbox_len(EMAIL_OUT)))
check('no new whatsapp alerts for a non-urgent report', outbox_len(WA_OUT) == wb2, (wb2, outbox_len(WA_OUT)))

print('--- urgent ANONYMOUS web report: deep link uses anonymous_report_id, not case_id ---')
eb3 = outbox_len(EMAIL_OUT)
r3 = json.loads(sh("""curl -s -X POST http://127.0.0.1:8110/api/reporting/submit-anonymous.php -H 'X-Requested-With: fetch' -H 'Accept: application/json' \
  -F concern_type=Bullying -F affected_who=Me -F incident_date=today -F location=Ground \
  -F description='anon urgent' -F current_risk=unsure"""))
check('anonymous submit succeeded', r3.get('success'), r3)
emails3 = outbox_tail(EMAIL_OUT, eb3)
check('2 emails sent for urgent anonymous report too', len(emails3) == 2, emails3)
check('deep link points at anonymous_report_id, not a case id',
      all('anonymous_report_id=' in e['body'] for e in emails3), emails3)
anon_id = sql(f"SELECT id FROM anonymous_reports WHERE case_reference_hash IS NOT NULL ORDER BY id DESC LIMIT 1")
rows3 = sql(f"SELECT COUNT(*) FROM notification_deliveries WHERE anonymous_report_id={anon_id}")
check('notification_deliveries correlates by anonymous_report_id (2 email + 1 whatsapp = 3)', rows3 == '3', rows3)
check('plaintext case_reference is NOT stored in notification_deliveries table at all',
      sql("SHOW COLUMNS FROM notification_deliveries LIKE 'case_reference'") == '')

print('--- admin panel surfaces delivery status ---')
COOKIES = '/tmp/notif_admin_cookies.txt'
sh(f"rm -f {COOKIES}")
def get_csrf(url):
    return sh(f"curl -s -b {COOKIES} -c {COOKIES} '{url}' | grep -o 'name=\"csrf_token\" value=\"[^\"]*\"' | sed 's/.*value=\"//;s/\"//'")

sh("php cron/create-admin-user.php 'Notif Admin' notifadmin@example.com 'TempPassword123!' 'Super Administrator'")
csrf = get_csrf('http://127.0.0.1:8110/admin/login.php')
sh(f"curl -s -b {COOKIES} -c {COOKIES} -o /dev/null -X POST http://127.0.0.1:8110/admin/login.php --data-urlencode 'csrf_token={csrf}' --data-urlencode 'email=notifadmin@example.com' --data-urlencode 'password=TempPassword123!'")
sh(f"curl -s -b {COOKIES} -c {COOKIES} http://127.0.0.1:8110/admin/2fa-setup.php > /tmp/notif_setup.html")
import re
secret = re.search(r'secret-display">([^<]+)</div>', open('/tmp/notif_setup.html').read()).group(1).replace(' ', '')
csrf2 = sh("grep -o 'name=\"csrf_token\" value=\"[^\"]*\"' /tmp/notif_setup.html | sed 's/.*value=\"//;s/\"//'")
code = sh(f"php -r \"require '/home/claude/zc/zc/app/bootstrap.php'; echo App\\\\Services\\\\Totp::currentCode('{secret}');\"")
sh(f"curl -s -b {COOKIES} -c {COOKIES} -o /dev/null -X POST http://127.0.0.1:8110/admin/2fa-setup.php --data-urlencode 'csrf_token={csrf2}' --data-urlencode 'code={code}'")
csrf3 = get_csrf('http://127.0.0.1:8110/admin/change-password.php')
sh(f"curl -s -b {COOKIES} -c {COOKIES} -o /dev/null -X POST http://127.0.0.1:8110/admin/change-password.php --data-urlencode 'csrf_token={csrf3}' --data-urlencode 'current_password=TempPassword123!' --data-urlencode 'new_password=BrandNewAdminPass456!' --data-urlencode 'confirm_password=BrandNewAdminPass456!'")

case_page = sh(f"curl -s -b {COOKIES} -c {COOKIES} 'http://127.0.0.1:8110/admin/cases/view.php?id={case_id}'")
check('case detail page shows "Notifications sent" section', 'Notifications sent' in case_page)
check('case detail page shows officer.phone@example.com as a recipient name is not exposed, but status+channel are',
      'email' in case_page and ('sent' in case_page))

anon_untriaged_page = sh(f"curl -s -b {COOKIES} -c {COOKIES} 'http://127.0.0.1:8110/admin/cases/view.php?anonymous_report_id={anon_id}'")
check('untriaged anonymous report page also shows its notification history', 'Notifications sent' in anon_untriaged_page)

print(f"\nRESULT: {ok} passed, {fail} failed")
