"""
This Ansible filter plugin generates a Glances password hash for a password.
"""

from __future__ import annotations

import hashlib
import uuid

from dotenv import load_dotenv

load_dotenv(override=False)

DOCUMENTATION = """
name: glances_password_hash
short_description: Generate a Glances password hash for a password.
version_added: "1.6.0"
description:
    - Generate a password hash in the salt$hash format expected by the Glances
      password file (e.g. glances.pwd), replicating Glances' own
      GlancesPassword.hash_password() PBKDF2-SHA256 double-hash scheme.
extends_documentation_fragment:
    - password_hash_input
"""

EXAMPLES = """
- name: Generate a Glances password hash for a password
  debug:
      msg: "{{ password | glances_password_hash }}"
"""

RETURN = r"""
_value:
    description: The Glances password hash for the password.
    type: str
"""


def glances_password_hash(password: str) -> str:
    """
    Generate a Glances password hash for a password.
    """

    iterations = 100000  # Number of iterations, matches Glances' GlancesPassword
    dklen = 128  # Derived key length in bytes, matches Glances' GlancesPassword

    # Glances first hashes the clear password with an empty salt (GlancesPassword.get_hash)
    inner_hash = hashlib.pbkdf2_hmac("sha256", password.encode(), b"", iterations, dklen=dklen).hex()

    # Then hashes that intermediate hash again with a random salt (GlancesPassword.hash_password)
    salt = uuid.uuid4().hex
    outer_hash = hashlib.pbkdf2_hmac("sha256", inner_hash.encode(), salt.encode(), iterations, dklen=dklen).hex()

    return f"{salt}${outer_hash}"


class FilterModule:  # pylint: disable=too-few-public-methods
    """
    This class is required for Ansible to recognize the filter plugin as a valid plugin.
    """

    def filters(self) -> dict[str, object]:
        """
        This method is required for Ansible to recognize the filter plugin as a valid plugin.
        """
        return {
            "glances_password_hash": glances_password_hash,
        }
