use super::*;

#[test]
fn rejects_invalid_lifecycle_dates() {
    let err = parse_err(
        r#"
                policy = "cargo-allow"
                [[allow]]
                id = "bad-date"
                kind = "panic"
                path = "src/lib.rs"
                owner = "core"
                classification = "test"
                reason = "fixture"
                expires = "2026-02-31"
                [allow.selector]
                ast_kind = "method_call"
                callee = "unwrap"
            "#,
    );

    assert!(err.contains("invalid expires date"));
}

#[test]
fn rejects_lifecycle_dates_before_created() {
    let err = parse_err(
        r#"
                policy = "cargo-allow"
                [[allow]]
                id = "bad-order"
                kind = "panic"
                path = "src/lib.rs"
                owner = "core"
                classification = "test"
                reason = "fixture"
                created = "2026-08-01"
                review_after = "2026-07-01"
                [allow.selector]
                ast_kind = "method_call"
                callee = "unwrap"
            "#,
    );

    assert!(err.contains("review_after must not be before created"));
}

#[test]
fn rejects_expiry_date_before_created() {
    let err = parse_err(
        r#"
                policy = "cargo-allow"
                [[allow]]
                id = "bad-expiry-order"
                kind = "panic"
                path = "src/lib.rs"
                owner = "core"
                classification = "test"
                reason = "fixture"
                created = "2026-08-01"
                expires = "2026-07-01"
                [allow.selector]
                ast_kind = "method_call"
                callee = "unwrap"
            "#,
    );

    assert!(err.contains("expires must not be before created"));
}

#[test]
fn rejects_review_after_later_than_expiry() {
    let err = parse_err(
        r#"
                policy = "cargo-allow"
                [[allow]]
                id = "bad-review-expiry-order"
                kind = "panic"
                path = "src/lib.rs"
                owner = "core"
                classification = "test"
                reason = "fixture"
                review_after = "2026-09-01"
                expires = "2026-08-01"
                [allow.selector]
                ast_kind = "method_call"
                callee = "unwrap"
            "#,
    );

    assert!(err.contains("review_after must not be after expires"));
}

#[test]
fn rejects_never_expiry_without_review_after_when_lifecycle_required() {
    let err = parse_err(
        r#"
                policy = "cargo-allow"

                [requirements]
                expires_or_review_after_required = true

                [[allow]]
                id = "never-without-review"
                kind = "panic"
                path = "src/lib.rs"
                owner = "core"
                classification = "test"
                reason = "fixture"
                expires = "never"
                [allow.selector]
                ast_kind = "method_call"
                callee = "unwrap"
            "#,
    );

    assert!(err.contains("missing expires or review_after"));
}

#[test]
fn accepts_never_expiry_with_review_after_when_lifecycle_required() {
    let cfg = parse_policy(
        r#"
                policy = "cargo-allow"

                [requirements]
                expires_or_review_after_required = true

                [[allow]]
                id = "never-with-review"
                kind = "panic"
                path = "src/lib.rs"
                owner = "core"
                classification = "test"
                reason = "fixture"
                review_after = "2026-08-01"
                expires = "never"
                [allow.selector]
                ast_kind = "method_call"
                callee = "unwrap"
            "#,
    )
    .unwrap_or_else(|err| std::panic::panic_any(format!("policy should parse: {err}")));

    assert_eq!(
        cfg.allow[0].lifecycle.review_after.as_deref(),
        Some("2026-08-01")
    );
    assert_eq!(cfg.allow[0].lifecycle.expires.as_deref(), Some("never"));
}

#[test]
fn rejects_baseline_debt_without_short_expiry() {
    let err = parse_err(
        r#"
                policy = "cargo-allow"
                [[allow]]
                id = "baseline-too-long"
                kind = "panic"
                path = "src/lib.rs"
                owner = "unowned"
                classification = "baseline_debt"
                reason = "Generated by cargo-allow propose; requires human review."
                created = "2026-05-26"
                expires = "2027-05-26"
                [allow.selector]
                ast_kind = "method_call"
                callee = "unwrap"
            "#,
    );

    assert!(err.contains("baseline_debt expires must be within"));
}

#[test]
fn rejects_baseline_debt_never_expiry() {
    let err = parse_err(
        r#"
                policy = "cargo-allow"
                [[allow]]
                id = "baseline-never"
                kind = "panic"
                path = "src/lib.rs"
                owner = "unowned"
                classification = "baseline_debt"
                reason = "Generated by cargo-allow propose; requires human review."
                created = "2026-05-26"
                expires = "never"
                [allow.selector]
                ast_kind = "method_call"
                callee = "unwrap"
            "#,
    );

    assert!(err.contains("baseline_debt requires expires"));
}
