//! Windows Service registration

use anyhow::{Context, Result};
use std::ffi::OsString;
use std::os::windows::ffi::OsStrExt;
use windows::Win32::System::Services::*;
use windows::Win32::Foundation::*;
use windows::core::PCWSTR;

pub fn install_service() -> Result<()> {
    let service_name = "OspabGuard";
    let display_name = "Ospab OSTP VPN Service";
    let description = "Manages secure OSTP VPN tunnel connections";

    let daemon_path = crate::get_install_path().join("ostp-daemon.exe");
    
    unsafe {
        // Open Service Control Manager
        let scm = OpenSCManagerW(
            PCWSTR::null(),
            PCWSTR::null(),
            SC_MANAGER_CREATE_SERVICE,
        )?;

        if scm.is_invalid() {
            anyhow::bail!("Failed to open Service Control Manager");
        }

        // Create service
        let service_name_wide = to_wide_string(service_name);
        let display_name_wide = to_wide_string(display_name);
        let binary_path_wide = to_wide_string(&daemon_path.to_string_lossy());

        let service = CreateServiceW(
            scm,
            PCWSTR(service_name_wide.as_ptr()),
            PCWSTR(display_name_wide.as_ptr()),
            SERVICE_ALL_ACCESS,
            SERVICE_WIN32_OWN_PROCESS,
            SERVICE_AUTO_START,
            SERVICE_ERROR_NORMAL,
            PCWSTR(binary_path_wide.as_ptr()),
            PCWSTR::null(),
            None,
            PCWSTR::null(),
            PCWSTR::null(),
            PCWSTR::null(),
        )?;

        if service.is_invalid() {
            CloseServiceHandle(scm)?;
            anyhow::bail!("Failed to create service");
        }

        // Set description
        let description_wide = to_wide_string(description);
        let mut service_desc = SERVICE_DESCRIPTIONW {
            lpDescription: windows::core::PWSTR(description_wide.as_ptr() as *mut _),
        };

        ChangeServiceConfig2W(
            service,
            SERVICE_CONFIG_DESCRIPTION,
            Some(&service_desc as *const _ as *const _),
        )?;

        CloseServiceHandle(service)?;
        CloseServiceHandle(scm)?;
    }

    tracing::info!("Service '{}' installed successfully", service_name);
    Ok(())
}

fn to_wide_string(s: &str) -> Vec<u16> {
    OsString::from(s)
        .encode_wide()
        .chain(std::iter::once(0))
        .collect()
}
