use crate::model::{
    FrontendError, LogRecord, Session, SpanEventRecord, SpanRecord, TauriEventRecord, TauriIpcCall,
    TauriWindowState,
};
use serde::{Deserialize, Serialize};
use thiserror::Error;

#[derive(Debug, Error)]
pub enum StorageError {
    #[error("storage backend error: {0}")]
    Backend(String),
}

pub trait TelemetryStore {
    fn create_session(&self, session: &Session) -> Result<(), StorageError>;
    fn insert_log(&self, log: &LogRecord) -> Result<(), StorageError>;
    fn insert_span(&self, span: &SpanRecord) -> Result<(), StorageError>;
    fn insert_span_event(&self, event: &SpanEventRecord) -> Result<(), StorageError>;
    fn insert_frontend_error(&self, error: &FrontendError) -> Result<(), StorageError>;
    fn insert_tauri_ipc_call(&self, call: &TauriIpcCall) -> Result<(), StorageError>;
    fn insert_tauri_event(&self, event: &TauriEventRecord) -> Result<(), StorageError>;
    fn insert_tauri_window_state(&self, window: &TauriWindowState) -> Result<(), StorageError>;
}

#[derive(Debug, Clone, Default, PartialEq, Eq)]
pub struct LogQuery {
    pub session_id: Option<String>,
    pub trace_id: Option<String>,
    pub limit: Option<usize>,
}

#[derive(Debug, Clone, Default, PartialEq, Eq)]
pub struct SpanQuery {
    pub session_id: Option<String>,
    pub trace_id: Option<String>,
    pub limit: Option<usize>,
}

#[derive(Debug, Clone, Default, PartialEq, Eq)]
pub struct SpanEventQuery {
    pub session_id: Option<String>,
    pub trace_id: Option<String>,
    pub limit: Option<usize>,
}

#[derive(Debug, Clone, Default, PartialEq, Eq)]
pub struct FrontendErrorQuery {
    pub session_id: Option<String>,
    pub trace_id: Option<String>,
    pub limit: Option<usize>,
}

#[derive(Debug, Clone, Default, PartialEq, Eq)]
pub struct TauriIpcQuery {
    pub session_id: Option<String>,
    pub trace_id: Option<String>,
    pub limit: Option<usize>,
}

#[derive(Debug, Clone, Default, PartialEq, Eq)]
pub struct TauriEventQuery {
    pub session_id: Option<String>,
    pub trace_id: Option<String>,
    pub limit: Option<usize>,
}

#[derive(Debug, Clone, Default, PartialEq, Eq)]
pub struct TauriWindowQuery {
    pub session_id: Option<String>,
    pub latest_only: bool,
    pub limit: Option<usize>,
}

#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RelatedTelemetryQuery {
    pub session_id: Option<String>,
    pub trace_id: Option<String>,
    pub window_label: Option<String>,
    pub start_time_unix_nanos: Option<i64>,
    pub end_time_unix_nanos: Option<i64>,
    pub limit: Option<usize>,
}

#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RelatedTelemetry {
    pub filter_notes: Vec<String>,
    pub spans: Vec<SpanRecord>,
    pub span_events: Vec<SpanEventRecord>,
    pub logs: Vec<LogRecord>,
    pub frontend_errors: Vec<FrontendError>,
    pub tauri_ipc_calls: Vec<TauriIpcCall>,
    pub tauri_events: Vec<TauriEventRecord>,
    pub tauri_windows: Vec<TauriWindowState>,
}
