//! Extended FFI bindings to the CP2K C API extensions
//!
//! This module contains unsafe extern functions that directly map to the
//! functions provided by libcp2k_extended.h. These should not be used directly
//! outside of this crate - use the safe wrappers instead.

use std::os::raw::{c_double, c_int};

unsafe extern "C" {
    /// Check if the force environment is a Quickstep (DFT) calculation
    pub fn cp2k_is_qs_env(env_id: c_int) -> c_int;

    /// Get the stress tensor in GPa
    pub fn cp2k_get_stress_tensor(env_id: c_int, stress: *mut c_double);

    /// Get the virial tensor in Hartree
    pub fn cp2k_get_virial_tensor(env_id: c_int, virial_tensor: *mut c_double);

    /// Get the number of molecular orbitals for a spin channel
    pub fn cp2k_get_nmo(env_id: c_int, spin: c_int) -> c_int;

    /// Get Kohn-Sham eigenvalues
    pub fn cp2k_get_eigenvalues(
        env_id: c_int,
        spin: c_int,
        eigenvalues: *mut c_double,
        nmax: c_int,
    ) -> c_int;

    /// Get orbital occupation numbers
    pub fn cp2k_get_occupation_numbers(
        env_id: c_int,
        spin: c_int,
        occupations: *mut c_double,
        nmax: c_int,
    ) -> c_int;

    /// Get HOMO and LUMO energies and indices
    pub fn cp2k_get_homo_lumo(
        env_id: c_int,
        spin: c_int,
        homo_energy: *mut c_double,
        lumo_energy: *mut c_double,
        homo_index: *mut c_int,
        lumo_index: *mut c_int,
    ) -> c_int;

    /// Get Mulliken atomic charges
    pub fn cp2k_get_mulliken_charges(env_id: c_int, charges: *mut c_double, natom: c_int) -> c_int;

    /// Get the dipole moment vector
    pub fn cp2k_get_dipole_moment(env_id: c_int, dipole: *mut c_double) -> c_int;

    /// Get SCF convergence information
    pub fn cp2k_get_scf_info(
        env_id: c_int,
        niter: *mut c_int,
        converged: *mut c_int,
        energy_change: *mut c_double,
    ) -> c_int;

    /// Get energy components (kinetic, Hartree, XC, etc.)
    pub fn cp2k_get_energy_components(
        env_id: c_int,
        e_kinetic: *mut c_double,
        e_hartree: *mut c_double,
        e_xc: *mut c_double,
        e_core: *mut c_double,
        e_total: *mut c_double,
    ) -> c_int;

    /// Get the number of electrons
    pub fn cp2k_get_nelectron(env_id: c_int, nelectron: *mut c_int) -> c_int;

    /// Get the Fermi energy
    pub fn cp2k_get_fermi_energy(env_id: c_int, e_fermi: *mut c_double) -> c_int;

    /// Get Hirshfeld atomic charges
    pub fn cp2k_get_hirshfeld_charges(env_id: c_int, charges: *mut c_double, natom: c_int)
    -> c_int;

    /// Get total spin (for spin-polarized calculations)
    pub fn cp2k_get_total_spin(env_id: c_int, total_spin: *mut c_double) -> c_int;

    /// Get grid metadata for the electron density
    pub fn cp2k_get_grid_info(
        env_id: c_int,
        spin: c_int,
        npts: *mut c_int,
        origin: *mut c_double,
        dh: *mut c_double,
    ) -> c_int;

    /// Get the full electron density on the realspace grid
    pub fn cp2k_get_electron_density_grid(
        env_id: c_int,
        spin: c_int,
        density: *mut c_double,
        nmax: c_int,
    ) -> c_int;

    /// Get dimensions of the MO coefficient matrix
    pub fn cp2k_get_mo_coeff_info(
        env_id: c_int,
        spin: c_int,
        nao: *mut c_int,
        nmo: *mut c_int,
    ) -> c_int;

    /// Get the full MO coefficient matrix
    pub fn cp2k_get_mo_coefficients(
        env_id: c_int,
        spin: c_int,
        coeffs: *mut c_double,
        nmax: c_int,
    ) -> c_int;

    /// Get the number of k-points (0 = Gamma-point-only calculation)
    pub fn cp2k_get_nkpoints(env_id: c_int) -> c_int;

    /// Get Kohn-Sham eigenvalues for one k-point and one spin channel
    pub fn cp2k_get_kpoint_eigenvalues(
        env_id: c_int,
        kpt_idx: c_int,
        spin: c_int,
        eigenvalues: *mut c_double,
        nmax: c_int,
    ) -> c_int;
}
