//! OSTP Windows Service - Background VPN Daemon
//!
//! Runs as a Windows Service (OspabGuard) managing the VPN tunnel.
//! Communicates with GUI via Named Pipe.

#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]

mod ipc;

use std::ffi::OsString;
use std::sync::{Arc, Mutex};
use std::time::Duration;
use anyhow::{Context, Result};
use windows_service::{
    define_windows_service,
    service::{
        ServiceControl, ServiceControlAccept, ServiceExitCode, ServiceStatus,
        ServiceType,
    },
    service_control_handler::{self, ServiceControlHandlerResult},
    service_dispatcher,
};
use windows_service::service::ServiceState as WinServiceState;

const SERVICE_NAME: &str = "OspabGuard";
const SERVICE_TYPE: ServiceType = ServiceType::OWN_PROCESS;

// Service state shared between control handler and service thread
pub struct ServiceState {
    pub should_stop: bool,
    pub is_connected: bool,
}

define_windows_service!(ffi_service_main, service_main);

fn main() -> Result<()> {
    // Try to start as a Windows Service
    service_dispatcher::start(SERVICE_NAME, ffi_service_main)
        .context("Failed to start service dispatcher")?;
    
    Ok(())
}

fn service_main(_arguments: Vec<OsString>) {
    if let Err(e) = run_service() {
        // Log error to Windows Event Log
        eprintln!("Service error: {}", e);
    }
}

fn run_service() -> Result<()> {
    // Setup logging to file (can't use stdout in service)
    let log_path = std::env::current_exe()?
        .parent()
        .unwrap()
        .join("ostp-daemon.log");
    
    let file = std::fs::OpenOptions::new()
        .create(true)
        .append(true)
        .open(log_path)?;
    
    tracing_subscriber::fmt()
        .with_writer(Mutex::new(file))
        .with_ansi(false)
        .init();

    tracing::info!("OspabGuard service starting");

    let state = Arc::new(Mutex::new(ServiceState {
        should_stop: false,
        is_connected: false,
    }));
    
    let state_clone = state.clone();

    // Register service control handler
    let event_handler = move |control_event| -> ServiceControlHandlerResult {
        match control_event {
            ServiceControl::Stop => {
                tracing::info!("Received STOP signal");
                state_clone.lock().unwrap().should_stop = true;
                ServiceControlHandlerResult::NoError
            }
            ServiceControl::Interrogate => ServiceControlHandlerResult::NoError,
            _ => ServiceControlHandlerResult::NotImplemented,
        }
    };

    let status_handle = service_control_handler::register(SERVICE_NAME, event_handler)?;

    // Tell Windows we're starting
    status_handle.set_service_status(ServiceStatus {
        service_type: SERVICE_TYPE,
        current_state: WinServiceState::Running,
        controls_accepted: ServiceControlAccept::STOP,
        exit_code: ServiceExitCode::Win32(0),
        checkpoint: 0,
        wait_hint: Duration::default(),
        process_id: None,
    })?;

    tracing::info!("Service is now running");

    // Main service loop
    let runtime = tokio::runtime::Runtime::new()?;
    runtime.block_on(async {
        service_loop(state).await
    })?;

    // Tell Windows we're stopping
    status_handle.set_service_status(ServiceStatus {
        service_type: SERVICE_TYPE,
        current_state: WinServiceState::Stopped,
        controls_accepted: ServiceControlAccept::empty(),
        exit_code: ServiceExitCode::Win32(0),
        checkpoint: 0,
        wait_hint: Duration::default(),
        process_id: None,
    })?;

    tracing::info!("Service stopped");
    Ok(())
}

async fn service_loop(state: Arc<Mutex<ServiceState>>) -> Result<()> {
    // Start Named Pipe IPC listener
    ipc::start_ipc_server(state.clone()).await?;
    tracing::info!("IPC server started");
    
    // TODO: Initialize TUN device (osn)
    // TODO: Initialize DNS resolver (osds)
    
    loop {
        {
            let state_lock = state.lock().unwrap();
            if state_lock.should_stop {
                tracing::info!("Stop signal received, exiting");
                break;
            }
        }
        
        // TODO: Handle IPC commands from GUI
        // TODO: Maintain OSTP tunnel connection
        // TODO: Auto-reconnect on failure
        
        tokio::time::sleep(Duration::from_millis(500)).await;
    }
    
    Ok(())
}
