# ABOUTME: User detection — parses /etc/passwd for login users, finds avatars and GTK themes.
# ABOUTME: Provides User dataclass and helper functions for the greeter UI.

import configparser
from dataclasses import dataclass
from pathlib import Path

NOLOGIN_SHELLS = {"/usr/sbin/nologin", "/sbin/nologin", "/bin/false", "/usr/bin/nologin"}
MIN_UID = 1000
MAX_UID = 65533

DEFAULT_PASSWD = Path("/etc/passwd")
DEFAULT_ACCOUNTSSERVICE_DIR = Path("/var/lib/AccountsService/icons")


@dataclass
class User:
    """Represents a system user suitable for login."""

    username: str
    uid: int
    gecos: str
    home: Path
    shell: str

    @property
    def display_name(self) -> str:
        """Return gecos if available, otherwise username."""
        return self.gecos if self.gecos else self.username


def get_users(passwd_path: Path = DEFAULT_PASSWD) -> list[User]:
    """Parse /etc/passwd and return users with UID in the login range."""
    users: list[User] = []

    if not passwd_path.exists():
        return users

    for line in passwd_path.read_text().splitlines():
        parts = line.split(":")
        if len(parts) < 7:
            continue

        username, _, uid_str, _, gecos, home, shell = parts[0], parts[1], parts[2], parts[3], parts[4], parts[5], parts[6]

        try:
            uid = int(uid_str)
        except ValueError:
            continue

        if uid < MIN_UID or uid > MAX_UID:
            continue
        if shell in NOLOGIN_SHELLS:
            continue
        if "/" in username or username.startswith("."):
            continue

        users.append(User(
            username=username,
            uid=uid,
            gecos=gecos,
            home=Path(home),
            shell=shell,
        ))

    return users


def get_avatar_path(
    username: str,
    accountsservice_dir: Path = DEFAULT_ACCOUNTSSERVICE_DIR,
    home_dir: Path | None = None,
) -> Path | None:
    """Find avatar for a user: AccountsService icon → ~/.face → None."""
    # AccountsService icon
    icon = accountsservice_dir / username
    if icon.exists() and not icon.is_symlink():
        return icon

    # ~/.face fallback
    if home_dir is not None:
        face = home_dir / ".face"
        if face.exists() and not face.is_symlink():
            return face

    return None


def get_user_gtk_theme(config_dir: Path | None = None) -> str | None:
    """Read the GTK theme name from a user's gtk-4.0/settings.ini."""
    if config_dir is None:
        return None

    settings_file = config_dir / "settings.ini"
    if not settings_file.exists():
        return None

    config = configparser.ConfigParser(interpolation=None)
    try:
        config.read(settings_file)
    except configparser.Error:
        return None

    if config.has_option("Settings", "gtk-theme-name"):
        return config.get("Settings", "gtk-theme-name")

    return None
