// Acceptance for P3.3 — the platform-agnostic ("common") artifact
// validation pass (subplan 05 "Common Validation" subset).
//
// Runs validate_artifact_file against the on-disk fixtures under
// examples/fixtures/ and asserts:
//   1. a GOOD artifact (correct size + sha256 + content type + extension
//      matching the platform) -> status .valid, reason .ok — for BOTH the
//      .apk/android_apk and .ipa/ios fixtures (cross-checks the ext map).
//   2. each tampered case -> status .invalid with the SPECIFIC reason:
//        - wrong declared size                 -> .size_mismatch
//        - wrong declared sha256               -> .digest_mismatch
//        - a .apk file declared as `ios`       -> .extension_mismatch
//        - a disallowed content type           -> .content_type_denied
//        - a path with no file                 -> .missing_file
//
// The expected sha256 values are the real digests of the fixtures,
// cross-checked against `shasum -a 256` and recomputed here by std.hash
// inside validate_artifact_file. Prints PASS/FAIL per case; exits non-zero
// if any case behaves unexpectedly so the runner counts it as a failure.
#import "modules/std.sx";
#import "../src/domain/platform.sx";
#import "../src/domain/artifact.sx";
#import "../src/validation/artifact_file.sx";

APK_PATH  :: "examples/fixtures/acme-1.2.3-android.apk";
IPA_PATH  :: "examples/fixtures/acme-1.2.3-ios.ipa";
APK_SHA   :: "55a008aa634d45313ef0a758624e0d2a356c156e507f28a2c60d19d38893af09";
IPA_SHA   :: "1581f47098fd83277fa07c3f234ec92d9ce456804738278ede4e76f7f7bced84";
APK_SIZE  :: 5;
IPA_SIZE  :: 5;
APK_CT    :: "application/vnd.android.package-archive";
IPA_CT    :: "application/octet-stream";
ZERO_SHA  :: "0000000000000000000000000000000000000000000000000000000000000000";

passed :: (o: ValidationOutcome) -> bool {
    return o.status == .valid and o.reason == .ok;
}

failed_with :: (o: ValidationOutcome, r: ValidationReason) -> bool {
    return o.status == .invalid and o.reason == r;
}

// ── good fixtures -> .valid / .ok ───────────────────────────────────────
check_good_apk :: () -> bool {
    o := validate_artifact_file(APK_PATH, APK_SIZE, APK_SHA, .android_apk, APK_CT);
    return passed(o);
}

check_good_ipa :: () -> bool {
    o := validate_artifact_file(IPA_PATH, IPA_SIZE, IPA_SHA, .ios, IPA_CT);
    return passed(o);
}

// ── tampered: wrong declared size -> .size_mismatch ─────────────────────
check_size_mismatch :: () -> bool {
    o := validate_artifact_file(APK_PATH, 999, APK_SHA, .android_apk, APK_CT);
    return failed_with(o, .size_mismatch);
}

// ── tampered: wrong declared sha256 -> .digest_mismatch ─────────────────
check_digest_mismatch :: () -> bool {
    o := validate_artifact_file(APK_PATH, APK_SIZE, ZERO_SHA, .android_apk, APK_CT);
    return failed_with(o, .digest_mismatch);
}

// ── tampered: .apk declared as `ios` -> .extension_mismatch ─────────────
// Size, digest, and content type all pass; only the extension/platform
// policy rejects it.
check_extension_mismatch :: () -> bool {
    o := validate_artifact_file(APK_PATH, APK_SIZE, APK_SHA, .ios, APK_CT);
    return failed_with(o, .extension_mismatch);
}

// ── tampered: disallowed content type -> .content_type_denied ───────────
check_content_type_denied :: () -> bool {
    o := validate_artifact_file(APK_PATH, APK_SIZE, APK_SHA, .android_apk, "text/plain");
    return failed_with(o, .content_type_denied);
}

// ── tampered: no file at path -> .missing_file ──────────────────────────
check_missing_file :: () -> bool {
    o := validate_artifact_file("examples/fixtures/does-not-exist.apk", APK_SIZE, APK_SHA, .android_apk, APK_CT);
    return failed_with(o, .missing_file);
}

run_case :: (label: string, ok: bool) -> i32 {
    if ok { print("  PASS  {}\n", label); return 0; }
    print("  FAIL  {}\n", label);
    return 1;
}

main :: () -> i32 {
    failures : i32 = 0;
    failures += run_case("good .apk/android_apk -> valid/ok",            check_good_apk());
    failures += run_case("good .ipa/ios -> valid/ok",                    check_good_ipa());
    failures += run_case("wrong size -> size_mismatch",                  check_size_mismatch());
    failures += run_case("wrong sha256 -> digest_mismatch",             check_digest_mismatch());
    failures += run_case(".apk declared as ios -> extension_mismatch",   check_extension_mismatch());
    failures += run_case("disallowed content type -> content_type_denied", check_content_type_denied());
    failures += run_case("missing file -> missing_file",                 check_missing_file());

    print("------------------------------------------------\n");
    if failures == 0 {
        print("validate_artifact_file: ALL CASES PASS\n");
        return 0;
    }
    print("validate_artifact_file: {} CASE(S) FAILED\n", failures);
    return 1;
}
