// SPDX-License-Identifier: GPL-3.0-or-later

use anyhow::{Context, Result};
use std::fs;
use std::path::Path;

use super::provider::{BacklightDisplayInfo, BacklightProvider};

/// Real backlight provider using /sys/class/backlight.
pub struct RealBacklightProvider;

impl BacklightProvider for RealBacklightProvider {
    fn detect(&self) -> Result<Vec<BacklightDisplayInfo>> {
        let backlight_dir = Path::new("/sys/class/backlight");
        if !backlight_dir.exists() {
            return Ok(Vec::new());
        }

        let mut result = Vec::new();
        let entries = fs::read_dir(backlight_dir)
            .context("Failed to read /sys/class/backlight")?;

        for entry in entries.flatten() {
            let name = entry.file_name().to_string_lossy().to_string();
            if name.starts_with('.') {
                continue;
            }

            let dir = entry.path();
            let max = read_sysfs_u32(&dir.join("max_brightness")).unwrap_or(100);
            let current = read_sysfs_u32(&dir.join("brightness")).unwrap_or(0);

            result.push(BacklightDisplayInfo { name, current, max });
        }

        Ok(result)
    }

    fn set_brightness(&self, name: &str, raw_value: u32) -> Result<()> {
        let path = Path::new("/sys/class/backlight")
            .join(name)
            .join("brightness");
        fs::write(&path, raw_value.to_string())
            .with_context(|| format!("Failed to write brightness to {:?}", path))
    }
}

fn read_sysfs_u32(path: &Path) -> Option<u32> {
    fs::read_to_string(path)
        .ok()
        .and_then(|s| s.trim().parse().ok())
}
