//! Capture d'écran du jeu demandée par l'éditeur.
//!
//! Quand `PendingScreenshot` est posé par le handler, ce système spawne une
//! entité `Screenshot::primary_window()`. L'observer encode le résultat en
//! PNG + base64 et l'envoie via le `DebugChannel`.

use bevy::prelude::*;
use san_motor::debug_protocol::GameToEditor;

use crate::{DebugChannel, PendingScreenshot};

/// Système Update : si une capture est demandée, spawne un Screenshot Bevy.
pub fn capture_game_screenshot(
    channel: Res<DebugChannel>,
    mut pending: ResMut<PendingScreenshot>,
    mut commands: Commands,
) {
    if !pending.0 {
        return;
    }
    pending.0 = false;

    let tx = channel.tx.clone();
    commands
        .spawn(bevy::render::view::screenshot::Screenshot::primary_window())
        .observe(move |captured: bevy::ecs::observer::On<bevy::render::view::screenshot::ScreenshotCaptured>| {
            let img = captured.image.clone();
            match img.try_into_dynamic() {
                Ok(dyn_img) => {
                    let rgb = dyn_img.to_rgb8();
                    let mut buf = std::io::Cursor::new(Vec::new());
                    if let Ok(()) = rgb.write_to(&mut buf, image::ImageFormat::Png) {
                        let png_bytes = buf.into_inner();
                        let b64 = base64_encode(&png_bytes);
                        let _ = tx.send(GameToEditor::ScreenshotData { png_base64: b64 });
                        info!("[san-debug] 📸 Screenshot envoyé ({} octets PNG)", png_bytes.len());
                    } else {
                        let _ = tx.send(GameToEditor::Error {
                            message: "Échec encodage PNG".into(),
                        });
                    }
                }
                Err(e) => {
                    let _ = tx.send(GameToEditor::Error {
                        message: format!("Screenshot conversion: {e}"),
                    });
                }
            }
        });
}

/// Encodeur base64 minimal (pas de dépendance externe).
fn base64_encode(data: &[u8]) -> String {
    const CHARS: &[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
    let mut result = String::with_capacity((data.len() + 2) / 3 * 4);
    for chunk in data.chunks(3) {
        let b0 = chunk[0] as u32;
        let b1 = chunk.get(1).copied().unwrap_or(0) as u32;
        let b2 = chunk.get(2).copied().unwrap_or(0) as u32;
        let n = (b0 << 16) | (b1 << 8) | b2;
        result.push(CHARS[((n >> 18) & 0x3F) as usize] as char);
        result.push(CHARS[((n >> 12) & 0x3F) as usize] as char);
        if chunk.len() > 1 { result.push(CHARS[((n >> 6) & 0x3F) as usize] as char); } else { result.push('='); }
        if chunk.len() > 2 { result.push(CHARS[(n & 0x3F) as usize] as char); } else { result.push('='); }
    }
    result
}
