#ifndef PAM_AUTH_H
#define PAM_AUTH_H

#include <string>
#include <memory>

/**
 * @brief PAM authentication result structure
 */
struct PamAuthResult {
    bool success;                       ///< Authentication success
    std::string userId;                 ///< User ID if successful
    std::string username;               ///< Username if successful
    std::string errorMessage;           ///< Error message if failed
    std::string errorCode;              ///< Error code for API responses
};

/**
 * @brief PAM authentication class
 *
 * This class provides PAM (Pluggable Authentication Modules) authentication
 * functionality for the stable-diffusion.cpp-rest server. It allows authentication
 * against system PAM modules, enabling integration with various authentication
 * backends (LDAP, Kerberos, local accounts, etc.).
 */
class PamAuth {
public:
    /**
     * @brief Construct a new Pam Auth object
     *
     * @param serviceName PAM service name (default: "stable-diffusion-rest")
     */
    explicit PamAuth(const std::string& serviceName = "stable-diffusion-rest");

    /**
     * @brief Destroy the Pam Auth object
     */
    ~PamAuth();

    /**
     * @brief Initialize PAM authentication
     *
     * @return true if initialization successful, false otherwise
     */
    bool initialize();

    /**
     * @brief Authenticate user with PAM
     *
     * @param username Username to authenticate
     * @param password Plain text password
     * @return PamAuthResult Authentication result
     */
    PamAuthResult authenticate(const std::string& username, const std::string& password);

    /**
     * @brief Check if PAM authentication is available
     *
     * @return true if PAM is available and initialized, false otherwise
     */
    bool isAvailable() const;

    /**
     * @brief Get PAM service name
     *
     * @return std::string PAM service name
     */
    std::string getServiceName() const;

    /**
     * @brief Set PAM service name
     *
     * @param serviceName PAM service name
     */
    void setServiceName(const std::string& serviceName);

private:
    std::string m_serviceName;          ///< PAM service name
    bool m_initialized;                  ///< Initialization status

    /**
     * @brief PAM conversation function
     *
     * This static function handles the conversation between PAM and the application
     * for password input and other authentication prompts.
     *
     * @param num_msg Number of messages
     * @param msg Messages from PAM
     * @param resp Response to PAM
     * @param appdata_ptr Application data pointer
     * @return int PAM return code
     */
    static int conversationFunction(int num_msg, const struct pam_message** msg,
                                   struct pam_response** resp, void* appdata_ptr);

    /**
     * @brief Internal PAM authentication implementation
     *
     * @param username Username to authenticate
     * @param password Plain text password
     * @return PamAuthResult Authentication result
     */
    PamAuthResult authenticateInternal(const std::string& username, const std::string& password);

    /**
     * @brief Convert PAM error code to error message
     *
     * @param pamError PAM error code
     * @return std::string Human-readable error message
     */
    std::string pamErrorToString(int pamError);

    /**
     * @brief Convert PAM error code to API error code
     *
     * @param pamError PAM error code
     * @return std::string API error code
     */
    std::string pamErrorToErrorCode(int pamError);
};

#endif // PAM_AUTH_H