use crate::Backend;
use serde::{Deserialize, Serialize};
use sqlx::FromRow;
use uuid::Uuid;

#[derive(FromRow, Debug, Serialize, Deserialize)]
pub struct Camera {
    pub uuid: String,
    pub desc: Option<String>,
    pub name: String,
}

impl Backend {
    pub(crate) async fn get_camera(&self, uuid: &Uuid) -> Option<Camera> {
        let uuid = uuid.to_string();
        match self {
            Backend::Sqlite(db) => sqlx::query_as!(
                Camera,
                "SELECT uuid, desc, name FROM camera WHERE uuid = ?",
                uuid
            )
            .fetch_optional(db)
            .await
            .unwrap(),
        }
    }

    pub(crate) async fn create_camera(&self, uuid: &Uuid, name: &str, desc: Option<&str>) -> Result<(), sqlx::Error> {
        let uuid_str = uuid.to_string();
        match self {
            Backend::Sqlite(db) => {
                sqlx::query!(
                    "INSERT INTO camera (uuid, name, desc) VALUES (?, ?, ?)",
                    uuid_str,
                    name,
                    desc
                )
                .execute(db)
                .await?;
                Ok(())
            }
        }
    }

    pub(crate) async fn update_camera(&self, uuid: &Uuid, name: &str, desc: Option<&str>) -> Result<bool, sqlx::Error> {
        let uuid_str = uuid.to_string();
        match self {
            Backend::Sqlite(db) => {
                let result = sqlx::query!(
                    "UPDATE camera SET name = ?, desc = ? WHERE uuid = ?",
                    name,
                    desc,
                    uuid_str
                )
                .execute(db)
                .await?;
                Ok(result.rows_affected() > 0)
            }
        }
    }

    pub(crate) async fn delete_camera(&self, uuid: &Uuid) -> Result<bool, sqlx::Error> {
        let uuid_str = uuid.to_string();
        match self {
            Backend::Sqlite(db) => {
                let result = sqlx::query!(
                    "DELETE FROM camera WHERE uuid = ?",
                    uuid_str
                )
                .execute(db)
                .await?;
                Ok(result.rows_affected() > 0)
            }
        }
    }

    pub(crate) async fn get_all_cameras(&self) -> Vec<Camera> {
        match self {
            Backend::Sqlite(db) => {
                sqlx::query_as!(
                    Camera,
                    "SELECT uuid, desc, name FROM camera ORDER BY name"
                )
                .fetch_all(db)
                .await
                .unwrap_or_default()
            }
        }
    }

    pub(crate) async fn amount_total_cameras(&self) -> i64 {
        match self {
            Backend::Sqlite(db) => {
                sqlx::query!("SELECT COUNT(*) as count FROM camera")
                    .fetch_one(db)
                    .await
                    .unwrap()
                    .count
            }
        }
    }
}
