use std::io::{self, Read};

use bridge_runtime::{
    build_failure_response, build_success_response, execute_runtime_input, execute_runtime_query,
    runtime_input_requests_result, RuntimeFailure, RuntimeInput,
};
use storage_convex_bridge::{BridgeError, BridgeErrorKind};

fn main() {
    let input = match read_stdin() {
        Ok(input) => input,
        Err(error) => {
            emit_failure(BridgeError {
                kind: BridgeErrorKind::Transport,
                message: format!("读取 bridge runtime stdin 失败: {error}"),
            });
        }
    };

    let runtime_input = match serde_json::from_str::<RuntimeInput>(&input) {
        Ok(runtime_input) => runtime_input,
        Err(error) => {
            emit_failure(BridgeError::validation(format!(
                "bridge runtime 输入 JSON 非法: {error}"
            )));
        }
    };

    if runtime_input_requests_result(&runtime_input) {
        match execute_runtime_query(runtime_input) {
            Ok(result) => {
                let payload = serde_json::to_string(&serde_json::json!({
                    "ok": true,
                    "result": result,
                }))
                .expect("bridge runtime query result 必须可序列化");
                println!("{payload}");
            }
            Err(error) => emit_failure(error),
        }
    } else {
        match execute_runtime_input(runtime_input) {
            Ok(plan) => {
                let payload = serde_json::to_string(&build_success_response(plan))
                    .expect("bridge runtime 成功响应必须可序列化");
                println!("{payload}");
            }
            Err(error) => emit_failure(error),
        }
    }
}

fn read_stdin() -> io::Result<String> {
    let mut buffer = String::new();
    io::stdin().read_to_string(&mut buffer)?;
    Ok(buffer)
}

fn emit_failure(error: BridgeError) -> ! {
    let payload =
        serde_json::to_string(&build_failure_response(error)).unwrap_or_else(|serialize_error| {
            serde_json::to_string(&RuntimeFailure {
                ok: false,
                error: bridge_runtime::RuntimeErrorPayload {
                    kind: "transport".into(),
                    message: format!("bridge runtime 错误序列化失败: {serialize_error}"),
                },
            })
            .expect("bridge runtime 兜底错误响应必须可序列化")
        });
    println!("{payload}");
    std::process::exit(1);
}
