#[cfg(not(target_arch = "wasm32"))]
pub mod local;
#[cfg(target_arch = "wasm32")]
pub mod wasm;
use anyhow::Result;
use base64::Engine;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
#[async_trait::async_trait(?Send)]
pub trait CoreDump: Clone {
    fn token(&self) -> Result<String>;
    fn base_api_url(&self) -> Result<String>;
    fn version(&self) -> Result<String>;
    async fn os(&self) -> Result<OsInfo>;
    fn is_tauri(&self) -> Result<bool>;
    async fn get_webrtc_stats(&self) -> Result<WebrtcStats>;
    async fn screenshot(&self) -> Result<String>;
    async fn upload_screenshot(&self) -> Result<String> {
        let screenshot = self.screenshot().await?;
        let cleaned = screenshot.trim_start_matches("data:image/png;base64,");
        let mut zoo = kittycad::Client::new(self.token()?);
        zoo.set_base_url(&self.base_api_url()?);
        let data = base64::engine::general_purpose::STANDARD.decode(cleaned)?;
        let links = zoo
            .meta()
            .create_debug_uploads(vec![kittycad::types::multipart::Attachment {
                name: "".to_string(),
                filename: Some("modeling-app/core-dump-screenshot.png".to_string()),
                content_type: Some("image/png".to_string()),
                data,
            }])
            .await
            .map_err(|e| anyhow::anyhow!(e.to_string()))?;
        if links.is_empty() {
            anyhow::bail!("Failed to upload screenshot");
        }
        Ok(links[0].clone())
    }
    async fn dump(&self) -> Result<AppInfo> {
        let webrtc_stats = self.get_webrtc_stats().await?;
        let os = self.os().await?;
        let screenshot_url = self.upload_screenshot().await?;
        let mut app_info = AppInfo {
            version: self.version()?,
            git_rev: git_rev::try_revision_string!().map_or_else(|| "unknown".to_string(), |s| s.to_string()),
            timestamp: chrono::Utc::now(),
            tauri: self.is_tauri()?,
            os,
            webrtc_stats,
            github_issue_url: None,
        };
        app_info.set_github_issue_url(&screenshot_url)?;
        Ok(app_info)
    }
}
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
#[ts(export)]
#[serde(rename_all = "snake_case")]
pub struct AppInfo {
    pub version: String,
    pub git_rev: String,
    #[ts(type = "string")]
    pub timestamp: chrono::DateTime<chrono::Utc>,
    pub tauri: bool,
    pub os: OsInfo,
    pub webrtc_stats: WebrtcStats,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub github_issue_url: Option<String>,
}
impl AppInfo {
    pub fn set_github_issue_url(&mut self, screenshot_url: &str) -> Result<()> {
        let tauri_or_browser_label = if self.tauri { "tauri" } else { "browser" };
        let labels = ["coredump", "bug", tauri_or_browser_label];
        let body = format!(
            r#"[Insert a description of the issue here]

<details>
<summary><b>Core Dump</b></summary>
```json
{}
```
</details>
"#,
            screenshot_url,
            serde_json::to_string_pretty(&self)?
        );
        let urlencoded: String = form_urlencoded::byte_serialize(body.as_bytes()).collect();
        self.github_issue_url = Some(format!(
            r#"https://github.com/{}/{}/issues/new?body={}&labels={}"#,
            "KittyCAD",
            "modeling-app",
            urlencoded,
            labels.join(",")
        ));
        Ok(())
    }
}
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
#[ts(export)]
#[serde(rename_all = "snake_case")]
pub struct OsInfo {
    #[serde(skip_serializing_if = "Option::is_none")]
    pub platform: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub arch: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub version: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub browser: Option<String>,
}
#[derive(Default, Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
#[ts(export)]
#[serde(rename_all = "snake_case")]
pub struct WebrtcStats {
    pub packets_lost: u32,
    pub frames_received: u32,
    pub frame_width: f32,
    pub frame_height: f32,
    pub frame_rate: f32,
    pub key_frames_decoded: u32,
    pub frames_dropped: u32,
    pub pause_count: u32,
    pub total_pauses_duration: f32,
    pub freeze_count: u32,
    pub total_freezes_duration: f32,
    pub pli_count: u32,
    pub jitter: f32,
}