//! v3.5 c4 — dogfood usecase #1: language switch (insight subflow).
//!
//! Port reference: `insight/tools/maestro/subflows/switch-lang-english.yaml`
//! (6-step idempotent flow tapping the dev-mode language picker on the
//! landing screen to force in-app locale to English).
//!
//! # Why this dogfood
//!
//! Hits the two smix-selector capabilities that landed in v3.5 c1-c3:
//!
//! - **c2** — `App.find()` / `app.tap(&id(...))` selector-type dispatch:
//!   the YAML uses `id: "dev-bubble"` / `"lang-picker-trigger"` /
//!   `"lang-option-en"`. The runner `/find` route only knows text
//!   selectors, so every one of these IDs has to ride the host-resolve
//!   fallback path (`tree() + resolve_selector_all`).
//! - **c3** — `raw_type → Role` derive in `runner-client::get_tree`:
//!   the dev-bubble overlay sits on top of the landing screen with
//!   raw_type="button" but no `role` field on the wire. Without c3's
//!   `derive_roles_recursive`, host-resolve sees `role=None` and the
//!   `tappable_subset_filter` (c1) can't distinguish the bubble from
//!   surrounding chrome.
//!
//! # Reversibility
//!
//! The YAML is documented as idempotent (tapping English when already on
//! English is a no-op). The flow does not log in, does not mutate
//! backend state, and does not require a teardown — safe to re-run from
//! any sim state where the dev-bubble is reachable on the landing screen.

use smix_sdk::{App, ExpectationFailure, id, text};
use std::time::Duration;

#[tokio::main(flavor = "multi_thread", worker_threads = 4)]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let port: u16 = std::env::var("SMIX_RUNNER_PORT")
        .ok()
        .and_then(|s| s.parse().ok())
        .unwrap_or(22087);
    let udid = std::env::var("SMIX_UDID").ok();

    println!("smix dogfood — insight language switch (v3.5 c4)");
    println!("================================================");
    println!("runner port: {port}");
    println!("udid:        {:?}", udid);
    println!();

    let mut app = App::connect_to_runner(port).await?;
    if let Some(u) = udid {
        app = app.with_udid(u);
    }

    let bundle_id =
        std::env::var("INSIGHT_BUNDLE_ID").unwrap_or_else(|_| "com.focusai.app.mobile".to_string());
    println!("foregrounding {bundle_id}");
    app.foreground(&bundle_id).await?;
    tokio::time::sleep(Duration::from_secs(2)).await;

    match switch_language_english(&app).await {
        Ok(()) => {
            println!();
            println!("✓ language switch flow passed (1-round dogfood)");
            println!("\n🎉 v3.5 c4 dogfood #1 — insight language switch ✅");
            Ok(())
        }
        Err(e) => {
            println!();
            println!("✗ language switch flow failed");
            for line in e.to_prompt().lines() {
                println!("    {line}");
            }
            Err("dogfood lang switch FAIL".into())
        }
    }
}

/// Port of `switch-lang-english.yaml`. Each step uses an id selector,
/// which is exactly the path c2 added the host-resolve fallback for.
async fn switch_language_english(app: &App) -> Result<(), ExpectationFailure> {
    println!("step 1: wait for dev-bubble (id) on landing");
    app.wait_for(&id("dev-bubble"), Duration::from_secs(60))
        .await?;

    println!("step 2: tap lang-picker-trigger (id)");
    app.tap(&id("lang-picker-trigger")).await?;

    println!("step 3: wait for lang-option-en (id)");
    app.wait_for(&id("lang-option-en"), Duration::from_secs(10))
        .await?;

    println!("step 4: tap lang-option-en (id)");
    app.tap(&id("lang-option-en")).await?;

    println!("step 5: wait for landing reload (text \"Log in to Insight\")");
    app.wait_for(&text("Log in to Insight"), Duration::from_secs(30))
        .await?;

    Ok(())
}
