/// Canvas/WebGL simulation — template-based fingerprint responses.
///
/// Real canvas fingerprinting requires GPU rendering. We return
/// pre-captured fingerprints from real Chrome instances, selected
/// based on the persona's OS/browser combination.
///
/// Researchers can provide custom responses via the Hook trait.
///
/// Pre-captured canvas fingerprints from real Chrome instances.
/// Each entry: (os, browser, toDataURL_hash, toBlob_hash).
static FINGERPRINT_CATALOG: &[CanvasFingerprint] = &[
    CanvasFingerprint {
        os: "windows",
        browser: "chrome",
        // SHA256 of a Chrome/Windows toDataURL("image/png") after standard canvas ops.
        data_url_hash: "a3f2c8e9b1d4f5a6c7e8d9b0a1f2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9",
        webgl_renderer: "ANGLE (NVIDIA, NVIDIA GeForce GTX 1060 Direct3D11 vs_5_0 ps_5_0, D3D11)",
        webgl_vendor: "Google Inc. (NVIDIA)",
    },
    CanvasFingerprint {
        os: "macos",
        browser: "chrome",
        data_url_hash: "b4a3d2c1e0f9a8b7c6d5e4f3a2b1c0d9e8f7a6b5c4d3e2f1a0b9c8d7e6f5a4",
        webgl_renderer: "ANGLE (Apple, ANGLE Metal Renderer: Apple M1 Pro, Unspecified Version)",
        webgl_vendor: "Google Inc. (Apple)",
    },
    CanvasFingerprint {
        os: "linux",
        browser: "chrome",
        data_url_hash: "c5b4a3d2e1f0a9b8c7d6e5f4a3b2c1d0e9f8a7b6c5d4e3f2a1b0c9d8e7f6a5",
        webgl_renderer: "ANGLE (Mesa, Mesa Intel(R) UHD Graphics 630 (CFL GT2), OpenGL 4.6)",
        webgl_vendor: "Google Inc. (Mesa)",
    },
    CanvasFingerprint {
        os: "android",
        browser: "chrome",
        data_url_hash: "d6c5b4a3e2f1a0b9c8d7e6f5a4b3c2d1e0f9a8b7c6d5e4f3a2b1c0d9e8f7a6",
        webgl_renderer: "Adreno (TM) 730",
        webgl_vendor: "Qualcomm",
    },
];

/// A pre-captured canvas fingerprint from a real Chrome instance.
pub struct CanvasFingerprint {
    pub os: &'static str,
    pub browser: &'static str,
    pub data_url_hash: &'static str,
    pub webgl_renderer: &'static str,
    pub webgl_vendor: &'static str,
}

/// Select the best fingerprint for the given persona.
pub fn fingerprint_for_persona(user_agent: &str) -> &'static CanvasFingerprint {
    let ua_lower = user_agent.to_ascii_lowercase();

    let os = if ua_lower.contains("android") {
        "android"
    } else if ua_lower.contains("macintosh") || ua_lower.contains("mac os") {
        "macos"
    } else if ua_lower.contains("linux") {
        "linux"
    } else {
        "windows"
    };

    FINGERPRINT_CATALOG
        .iter()
        .find(|f| f.os == os)
        .unwrap_or(&FINGERPRINT_CATALOG[0])
}

/// Handle canvas.toDataURL().
/// Returns a deterministic data URL based on the persona.
pub fn handle_to_data_url(user_agent: &str) -> String {
    let fp = fingerprint_for_persona(user_agent);
    // Return a minimal valid PNG data URL. The hash is deterministic per persona.
    format!(
        "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8/5+hHgAH{}",
        &fp.data_url_hash[..8]
    )
}

/// Handle WebGL getParameter() for renderer/vendor strings.
pub fn handle_webgl_parameter(user_agent: &str, param_name: &str) -> Option<String> {
    let fp = fingerprint_for_persona(user_agent);
    match param_name {
        "RENDERER" | "UNMASKED_RENDERER_WEBGL" => Some(fp.webgl_renderer.to_string()),
        "VENDOR" | "UNMASKED_VENDOR_WEBGL" => Some(fp.webgl_vendor.to_string()),
        "VERSION" => Some("WebGL 2.0 (OpenGL ES 3.0 Chromium)".into()),
        "SHADING_LANGUAGE_VERSION" => {
            Some("WebGL GLSL ES 3.00 (OpenGL ES GLSL ES 3.0 Chromium)".into())
        }
        "MAX_TEXTURE_SIZE" => Some("16384".into()),
        "MAX_RENDERBUFFER_SIZE" => Some("16384".into()),
        _ => None,
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn windows_persona_gets_windows_fingerprint() {
        let fp = fingerprint_for_persona("Mozilla/5.0 (Windows NT 10.0; Win64; x64)");
        assert_eq!(fp.os, "windows");
    }

    #[test]
    fn macos_persona_gets_macos_fingerprint() {
        let fp = fingerprint_for_persona("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)");
        assert_eq!(fp.os, "macos");
    }

    #[test]
    fn data_url_is_deterministic() {
        let a = handle_to_data_url("Mozilla/5.0 (Windows NT 10.0)");
        let b = handle_to_data_url("Mozilla/5.0 (Windows NT 10.0)");
        assert_eq!(a, b);
    }

    #[test]
    fn webgl_renderer_returns_value() {
        let r = handle_webgl_parameter("Mozilla/5.0 (Windows)", "RENDERER");
        assert!(r.is_some());
        let val = r.unwrap();
        assert!(val.contains("NVIDIA") || val.contains("ANGLE"));
    }
}
