#!/usr/bin/env python3
"""Phase 3 wpClaimToken fixture checks.

Script-style by design so older hosts do not need pytest. Run with:
/opt/alt/python39/bin/python3 tests/test_phase3_wp_claim_token_fixtures.py
"""
from __future__ import annotations

import json
import os
import re
import subprocess
from pathlib import Path

ROOT = Path(__file__).resolve().parents[1]


def run_php(code: str) -> str:
    result = subprocess.run(
        ["php", "-d", "display_errors=1", "-r", code],
        cwd=str(ROOT),
        text=True,
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE,
        check=False,
    )
    if result.returncode != 0:
        raise AssertionError(f"PHP failed\nSTDOUT:\n{result.stdout}\nSTDERR:\n{result.stderr}")
    return result.stdout.strip()


def assert_php_claim_validation_behaviour() -> None:
    code = r'''
require __DIR__ . "/lib/vectra_wp_claim_token.php";
$secret = str_repeat("a", 64);
$config = ["claim_tokens" => [
    "secret" => $secret,
    "issuer" => "https://audionerdz.net",
    "audience" => "vectra-drm-staging",
    "scope" => "account_binding",
    "kid" => "staging-2026-05",
    "max_future_iat_seconds" => 60,
]];
$now = time();
$payload = [
    "iss" => "https://audionerdz.net",
    "aud" => "vectra-drm-staging",
    "scope" => "account_binding",
    "wp_user_id" => 123,
    "sub" => "wp:123",
    "iat" => $now,
    "exp" => $now + 600,
    "jti" => bin2hex(random_bytes(32)),
];
$token = vectra_wp_claim_build_token($payload, $secret, "staging-2026-05");
$ok = vectra_wp_claim_validate_token($token, $config, null, false);
$expired = $payload;
$expired["jti"] = bin2hex(random_bytes(32));
$expired["iat"] = $now - 700;
$expired["exp"] = $now - 100;
$expiredToken = vectra_wp_claim_build_token($expired, $secret, "staging-2026-05");
$expiredCode = "";
try { vectra_wp_claim_validate_token($expiredToken, $config, null, false); }
catch (VectraWpClaimException $e) { $expiredCode = $e->safeCode(); }
$tampered = explode(".", $token);
$tampered[1] = strtr(base64_encode(json_encode(array_merge($payload, ["wp_user_id" => 124, "sub" => "wp:124"]), JSON_UNESCAPED_SLASHES)), "+/", "-_");
$tampered[1] = rtrim($tampered[1], "=");
$tamperedCode = "";
try { vectra_wp_claim_validate_token(implode(".", $tampered), $config, null, false); }
catch (VectraWpClaimException $e) { $tamperedCode = $e->safeCode(); }
$badHeader = ["typ" => "vectra-wp-claim", "alg" => "none", "v" => 1];
$badToken = vectra_wp_claim_b64url_encode(json_encode($badHeader)) . "." . explode(".", $token)[1] . "." . explode(".", $token)[2];
$algCode = "";
try { vectra_wp_claim_validate_token($badToken, $config, null, false); }
catch (VectraWpClaimException $e) { $algCode = $e->safeCode(); }
echo json_encode([
    "wp_user_id" => $ok["wp_user_id"],
    "jti_hash_len" => strlen($ok["jti_hash"]),
    "expired" => $expiredCode,
    "tampered" => $tamperedCode,
    "alg" => $algCode,
], JSON_UNESCAPED_SLASHES);
'''
    data = json.loads(run_php(code))
    assert data["wp_user_id"] == 123
    assert data["jti_hash_len"] == 64
    assert data["expired"] == "token_expired"
    assert data["tampered"] == "invalid_signature"
    assert data["alg"] == "invalid_alg"
    print("PASS assert_php_claim_validation_behaviour")


def assert_static_security_requirements() -> None:
    lib = (ROOT / "lib" / "vectra_wp_claim_token.php").read_text()
    endpoint = (ROOT / "claim_token_validate.php").read_text()
    bootstrap = (ROOT / "config" / "vectra_bootstrap.php").read_text()

    assert "hash_hmac('sha256'" in lib
    assert "hash_equals" in lib
    assert "invalid_alg" in lib and "HS256" in lib
    assert "vectra_wp_claim_b64url_decode_strict" in lib
    assert "preg_match('/^[A-Za-z0-9_-]+$/" in lib
    assert "vectra_wp_claim_jti_hash" in lib
    assert "INSERT INTO vectra_consumed_jti (jti) VALUES (:jti_hash)" in lib
    assert "token_replayed" in lib
    assert "claim_tokens.secret" in bootstrap
    assert "Authorization" not in endpoint
    assert "full wpClaimToken" not in endpoint
    assert "staging_only" in endpoint
    print("PASS assert_static_security_requirements")


def assert_no_client_or_read_path_flip() -> None:
    activate = (ROOT / "activate.php").read_text(errors="ignore")
    assert "claim_token_validate" not in activate
    assert "vectra_wp_claim" not in activate
    print("PASS assert_no_client_or_read_path_flip")


def main() -> None:
    assert_php_claim_validation_behaviour()
    assert_static_security_requirements()
    assert_no_client_or_read_path_flip()
    print("PASS all 3 Phase 3 wpClaimToken fixture tests")


if __name__ == "__main__":
    main()
