use super::*;

#[test]
fn advances_to_target() {
    let mut state = state();
    let result = execute_step_command(
        &mut state,
        &StepCommand::AdvanceTo {
            calendar: CalendarPoint {
                year: 1830,
                month_slot: 0,
                phase_slot: 0,
                tick_slot: 5,
            },
        },
    )
    .expect("advance_to should succeed");

    assert_eq!(result.steps_executed, 5);
    assert_eq!(state.calendar.tick_slot, 5);
    assert_eq!(state.world_restore.packed_year_word_raw_u16, Some(1830));
    assert_eq!(state.world_restore.partial_year_progress_raw_u8, Some(1));
    assert_eq!(
        state.world_restore.current_calendar_tuple_word_raw_u32,
        Some(0x0101_0726)
    );
    assert_eq!(
        state.world_restore.current_calendar_tuple_word_2_raw_u32,
        Some(0x2801_0001)
    );
    assert_eq!(
        state.world_restore.absolute_counter_raw_u32,
        Some(885_427_240)
    );
    assert_eq!(
        state.world_restore.absolute_counter_mirror_raw_u32,
        Some(885_427_240)
    );
    assert_eq!(
        state.world_restore.selected_year_gap_scalar_raw_u32,
        Some((1.0f32 / 3.0).to_bits())
    );
    assert_eq!(
        state
            .world_restore
            .selected_year_gap_scalar_value_f32_text
            .as_deref(),
        Some("0.333333")
    );
}

#[test]
fn year_rollover_step_runs_periodic_boundary_services() {
    let mut state = RuntimeState {
        calendar: CalendarPoint {
            year: 1830,
            month_slot: MONTH_SLOTS_PER_YEAR - 1,
            phase_slot: PHASE_SLOTS_PER_MONTH - 1,
            tick_slot: crate::calendar::TICKS_PER_PHASE - 1,
        },
        event_runtime_records: vec![RuntimeEventRecord {
            record_id: 77,
            trigger_kind: 1,
            active: true,
            service_count: 0,
            marks_collection_dirty: false,
            one_shot: false,
            has_fired: false,
            conditions: Vec::new(),
            effects: vec![RuntimeEffect::SetWorldFlag {
                key: "world.periodic_rollover_service_fired".to_string(),
                value: true,
            }],
        }],
        ..state()
    };

    let result = execute_step_command(&mut state, &StepCommand::StepCount { steps: 1 })
        .expect("year rollover step should run periodic boundary services");

    assert_eq!(result.steps_executed, 1);
    assert_eq!(
        result.boundary_events,
        vec![BoundaryEvent {
            kind: "year_rollover".to_string(),
            calendar: CalendarPoint {
                year: 1831,
                month_slot: 0,
                phase_slot: 0,
                tick_slot: 0,
            },
        }]
    );
    assert_eq!(state.service_state.periodic_boundary_calls, 1);
    assert_eq!(state.service_state.total_event_record_services, 1);
    assert_eq!(
        state
            .world_flags
            .get("world.periodic_rollover_service_fired"),
        Some(&true)
    );
    assert_eq!(state.world_restore.packed_year_word_raw_u16, Some(1831));
    assert_eq!(state.world_restore.partial_year_progress_raw_u8, Some(1));
    assert_eq!(
        state.world_restore.current_calendar_tuple_word_raw_u32,
        Some(0x0101_0727)
    );
    assert_eq!(
        state.world_restore.current_calendar_tuple_word_2_raw_u32,
        Some(0x0001_0001)
    );
    assert_eq!(
        state.world_restore.absolute_counter_raw_u32,
        Some(885_911_040)
    );
    assert_eq!(
        state.world_restore.absolute_counter_mirror_raw_u32,
        Some(885_911_040)
    );
    assert_eq!(
        state.world_restore.selected_year_gap_scalar_raw_u32,
        Some((1.0f32 / 3.0).to_bits())
    );
    assert_eq!(
        state
            .world_restore
            .selected_year_gap_scalar_value_f32_text
            .as_deref(),
        Some("0.333333")
    );
    assert!(
        result
            .service_events
            .iter()
            .any(|event| event.trigger_kind == Some(1))
    );
    assert!(
        result
            .service_events
            .iter()
            .any(|event| event.kind == "annual_finance_policy")
    );
}

#[test]
fn rejects_backward_target() {
    let mut state = state();
    state.calendar.tick_slot = 3;

    let result = execute_step_command(
        &mut state,
        &StepCommand::AdvanceTo {
            calendar: CalendarPoint {
                year: 1830,
                month_slot: 0,
                phase_slot: 0,
                tick_slot: 2,
            },
        },
    );

    assert!(result.is_err());
}
