use trazaeo::capture::{build_capture_envelope, CaptureSessionInput, CapturedSegment};
use trazaeo::checkpoint::CheckpointArtifact;
use trazaeo::envelope::{make_attestation, ArtifactRecord, Attestation};
use trazaeo::proof_log::{build_proof_log_commitment, verify_proof_log_commitment_linkage};
use trazaeo::publish_pipeline::{build_publish_envelope, PublishInput};
use trazaeo::reward::{build_reward_claim, settle_reward_claim, RewardClaim, SettlementDomain};
use trazaeo::transform_pipeline::{build_transform_envelope, TransformStageInput};
use trazaeo::trust::TrustPolicy;
use trazaeo::utils::Hash;
use trazaeo::verification::{is_report_success, verify_publish_envelope, VerificationMode};

const TEST_SIGNING_KEY_HEX: &str =
    "4f3edf983ac636a65a842ce7c78d9aa706d3b113bce036f9a4f5762b76f70f18";

/// Tests that e2e flow transport capture to reward claim.
#[test]
fn e2e_flow_transport_capture_to_reward_claim() {
    let capture_input = CaptureSessionInput {
        schema_version: "1.0.0".to_string(),
        issued_at: "2026-01-01T00:00:00Z".to_string(),
        subject_id: "capture-1".to_string(),
        capture_role: "transport".to_string(),
        capture_actor_id: "station-a".to_string(),
        capture_system_id: "rx-1".to_string(),
        capture_window: "2026-01-01T00:00:00Z/2026-01-01T00:05:00Z".to_string(),
        input_refs: vec![],
        output_refs: vec!["obj://raw/1".to_string()],
        content_descriptor_ref: None,
        content_descriptor_hash: None,
        key_id: "key-1".to_string(),
        policy_profile_id: Some("policy-1".to_string()),
    };
    let messages = vec![
        CapturedSegment {
            segment_id: "seg-1".to_string(),
            payload: b"abc".to_vec(),
        },
        CapturedSegment {
            segment_id: "seg-2".to_string(),
            payload: b"def".to_vec(),
        },
    ];
    let mut capture = build_capture_envelope(
        &capture_input,
        &messages,
        make_attestation(
            "station",
            TEST_SIGNING_KEY_HEX,
            "2026-01-01T00:00:00Z",
            b"capture-seed",
        )
        .expect("build capture attestation"),
    );
    let capture_payload = capture.canonical_attestation_payload_bytes();
    let capture_attestation = make_attestation(
        "station",
        TEST_SIGNING_KEY_HEX,
        "2026-01-01T00:00:00Z",
        &capture_payload,
    )
    .expect("build capture attestation");
    capture.key_id = capture_attestation.key_id.clone();
    capture.attestations = vec![capture_attestation];
    assert!(capture.validate().is_ok());

    let transform_stage = TransformStageInput {
        schema_version: "1.0.0".to_string(),
        issued_at: "2026-01-01T00:10:00Z".to_string(),
        subject_id: "transform-1".to_string(),
        transform_job_id: "job-1".to_string(),
        transform_stage: "nc_to_zarr".to_string(),
        input_refs: vec!["obj://raw/1".to_string()],
        output_refs: vec!["obj://zarr/1".to_string()],
        input_artifacts: vec![ArtifactRecord {
            artifact_id: "input-1".to_string(),
            artifact_ref: "obj://raw/1".to_string(),
            content_root_hash: capture.content_root_hash.clone(),
        }],
        output_artifacts: vec![ArtifactRecord {
            artifact_id: "output-1".to_string(),
            artifact_ref: "obj://zarr/1".to_string(),
            content_root_hash: hex::encode(Hash([2u8; 32]).0),
        }],
        toolchain: "rust".to_string(),
        parameters_ref: "cfg://1".to_string(),
        parameters_hash: "cfg-hash".to_string(),
        determinism_profile: "det-v1".to_string(),
        runtime_env_ref: Some("oci://img".to_string()),
        runtime_env_hash: Some("img-hash".to_string()),
        provenance_start_mode: "transport_capture".to_string(),
        source_manifest_ref: None,
        source_manifest_hash: None,
        source_root_hash: None,
        transform_spec_ref: None,
        transform_spec_hash: None,
        chunking_profile_ref: None,
        chunking_profile_hash: None,
        execution_manifest_ref: None,
        execution_manifest_hash: None,
        runtime_manifest_ref: None,
        runtime_manifest_hash: None,
        key_id: "key-1".to_string(),
    };
    let mut transform = build_transform_envelope(
        &transform_stage,
        make_attestation(
            "transformer",
            TEST_SIGNING_KEY_HEX,
            "2026-01-01T00:00:00Z",
            b"transform-seed",
        )
        .expect("build transform attestation"),
    );
    let transform_payload = transform.canonical_attestation_payload_bytes();
    let transform_attestation = make_attestation(
        "transformer",
        TEST_SIGNING_KEY_HEX,
        "2026-01-01T00:00:00Z",
        &transform_payload,
    )
    .expect("build transform attestation");
    transform.key_id = transform_attestation.key_id.clone();
    transform.attestations = vec![transform_attestation];
    assert!(transform.validate().is_ok());

    let publish_input = PublishInput {
        schema_version: "1.0.0".to_string(),
        issued_at: "2026-01-01T00:20:00Z".to_string(),
        subject_id: "publish-1".to_string(),
        dataset_id: "sst".to_string(),
        dataset_version: "v1".to_string(),
        input_refs: vec!["obj://zarr/1".to_string()],
        output_refs: vec!["obj://release/1".to_string()],
        published_artifacts: vec![CheckpointArtifact {
            artifact_id: "artifact-1".to_string(),
            content_root_hash: hex::encode(Hash([9u8; 32]).0),
            content_descriptor_ref: None,
            content_descriptor_hash: None,
            media_type: "application/vnd+zarr".to_string(),
        }],
        primary_artifact_id: "artifact-1".to_string(),
        checkpoint_manifest_ref: "checkpoint://1".to_string(),
        checkpoint_manifest_hash: hex::encode(Hash([9u8; 32]).0),
        checkpoint_id: "checkpoint-1".to_string(),
        checkpoint_log_root_hash: hex::encode(Hash([9u8; 32]).0),
        lineage_refs: vec!["capture://1".to_string(), "transform://1".to_string()],
        verification_policy_id: "verify-default".to_string(),
        key_id: "key-1".to_string(),
        stac_refs: vec![],
        reward_context_ref: None,
        reward_context_hash: None,
        provenance_start_mode: "transport_capture".to_string(),
        bootstrap_origin_label: None,
        reward_eligible: true,
    };
    let mut publish = build_publish_envelope(
        &publish_input,
        make_attestation(
            "publisher",
            TEST_SIGNING_KEY_HEX,
            "2026-01-01T00:00:00Z",
            b"publish-seed",
        )
        .expect("build publish attestation"),
    );
    let publish_key_seed = make_attestation(
        "publisher",
        TEST_SIGNING_KEY_HEX,
        "2026-01-01T00:00:00Z",
        b"",
    )
    .expect("derive publish key id");
    publish.key_id = publish_key_seed.key_id.clone();
    publish.attestations = vec![Attestation {
        signer_id: "publisher".to_string(),
        key_id: publish_key_seed.key_id.clone(),
        signature: String::new(),
        signed_at: "2026-01-01T00:00:00Z".to_string(),
    }];
    let publish_payload = publish.canonical_attestation_payload_bytes();
    let publish_attestation = make_attestation(
        "publisher",
        TEST_SIGNING_KEY_HEX,
        "2026-01-01T00:00:00Z",
        &publish_payload,
    )
    .expect("build publish attestation");
    publish.attestations = vec![publish_attestation];
    assert!(publish.validate().is_ok());

    let mut trust = TrustPolicy::new();
    trust.allow_key(&publish.key_id);
    let report = verify_publish_envelope(&publish, VerificationMode::Sampled, &trust);
    assert!(is_report_success(&report));

    let commitment =
        build_proof_log_commitment(&publish, "2026-01-01T00:21:00Z", "tx-123", "attestor-key");
    assert!(verify_proof_log_commitment_linkage(&publish, &commitment).is_ok());

    let claim = RewardClaim {
        reward_claim_id: "claim-1".to_string(),
        actor_id: "actor-1".to_string(),
        action_type: "publish".to_string(),
        event_time_window: "2026-01-01T00:00:00Z/2026-01-01T01:00:00Z".to_string(),
        evidence_refs: vec!["publish://1".to_string()],
        proof_log_entry_refs: vec![commitment.entry_id.clone()],
        quality_score_ref: None,
        payout_recipient: "wallet-1".to_string(),
        payout_policy_id: "policy-1".to_string(),
    };

    let built_claim =
        build_reward_claim(claim, &report, &publish, &[commitment]).expect("build claim");
    let settlement = settle_reward_claim(
        &built_claim,
        "2026-01-01T02:00:00Z",
        &SettlementDomain {
            chain_id: "solana-mainnet".to_string(),
            settlement_window: "2026-W01".to_string(),
            policy_id: "policy-1".to_string(),
            schema_version: "v1".to_string(),
            nonce: "nonce-1".to_string(),
        },
    );
    assert_eq!(settlement.reward_claim_id, "claim-1");
    assert!(!settlement.settlement_hash.is_empty());
}
