//! ZK-Rollup Sequencer Node
//!
//! Collects transactions, builds batches, and coordinates proof generation.

use std::env;
use std::net::SocketAddr;
use std::sync::Arc;

use synor_zk::rollup::{RollupConfig, RollupManager};
use synor_zk::proof::{ProofSystem, ProofSystemBackend};
use synor_zk::state::StateTree;

/// Sequencer configuration from environment/config file
struct SequencerConfig {
    node_id: String,
    api_addr: SocketAddr,
    prover_addr: SocketAddr,
    metrics_addr: SocketAddr,
    max_batch_size: usize,
    proof_backend: ProofSystemBackend,
    l1_rpc: String,
}

impl Default for SequencerConfig {
    fn default() -> Self {
        Self {
            node_id: env::var("NODE_ID").unwrap_or_else(|_| "zk-sequencer-1".to_string()),
            api_addr: "0.0.0.0:3001".parse().unwrap(),
            prover_addr: "0.0.0.0:3002".parse().unwrap(),
            metrics_addr: "0.0.0.0:9001".parse().unwrap(),
            max_batch_size: env::var("MAX_BATCH_SIZE")
                .ok()
                .and_then(|s| s.parse().ok())
                .unwrap_or(1000),
            proof_backend: match env::var("PROOF_BACKEND").as_deref() {
                Ok("plonk") => ProofSystemBackend::Plonk,
                Ok("stark") => ProofSystemBackend::Stark,
                _ => ProofSystemBackend::Groth16,
            },
            l1_rpc: env::var("L1_RPC").unwrap_or_else(|_| "http://localhost:8545".to_string()),
        }
    }
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Initialize logging
    tracing_subscriber::fmt()
        .with_env_filter(
            tracing_subscriber::EnvFilter::from_default_env()
                .add_directive("synor_zk=info".parse()?)
        )
        .init();

    let config = SequencerConfig::default();

    tracing::info!(
        node_id = %config.node_id,
        api_addr = %config.api_addr,
        proof_backend = ?config.proof_backend,
        "Starting ZK-Rollup Sequencer"
    );

    // Initialize state tree
    let state_tree = Arc::new(StateTree::new(32));
    tracing::info!("State tree initialized with depth 32");

    // Initialize proof system
    let proof_system = Arc::new(ProofSystem::new(config.proof_backend));
    tracing::info!(backend = ?config.proof_backend, "Proof system initialized");

    // Initialize rollup manager
    let rollup_config = RollupConfig {
        max_batch_size: config.max_batch_size,
        min_batch_size: 10,
        batch_timeout: std::time::Duration::from_secs(60),
        tree_depth: 32,
        bridge_address: None,
    };

    let rollup_manager = RollupManager::with_config(rollup_config);
    tracing::info!(
        max_batch = config.max_batch_size,
        "Rollup manager initialized"
    );

    // Start health check endpoint
    let health_handle = tokio::spawn(async move {
        use std::io::{Read, Write};
        use std::net::TcpListener;

        let listener = TcpListener::bind("0.0.0.0:3001").expect("Failed to bind health check");
        tracing::info!("Health check listening on :3001");

        for stream in listener.incoming() {
            if let Ok(mut stream) = stream {
                let mut buffer = [0; 1024];
                let _ = stream.read(&mut buffer);

                let response = if buffer.starts_with(b"GET /health") {
                    "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\n\r\n{\"status\":\"healthy\"}"
                } else {
                    "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\n\r\n{\"service\":\"zk-sequencer\"}"
                };

                let _ = stream.write_all(response.as_bytes());
            }
        }
    });

    tracing::info!("ZK-Rollup Sequencer running");

    // Wait for shutdown signal
    tokio::signal::ctrl_c().await?;
    tracing::info!("Shutting down ZK-Rollup Sequencer");

    health_handle.abort();

    Ok(())
}
