use crate::doqium_data_client::apis::{notebooks_api, notes_api, workspaces_api};
use crate::doqium_data_client::models::{Note, Notebook, Workspace};
use anyhow::Result;
use uuid::Uuid;

use super::DoqiumClient;

pub struct DataRepository<'a> {
    client: &'a DoqiumClient,
}

impl<'a> DataRepository<'a> {
    pub fn new(client: &'a DoqiumClient) -> Self {
        Self { client }
    }

    pub async fn list_workspaces(&self) -> Result<Vec<Workspace>> {
        let workspaces = workspaces_api::list_workspaces(self.client.data_config()).await?;
        Ok(workspaces)
    }

    pub async fn create_workspace(&self, name: &str) -> Result<String> {
        let body = crate::doqium_data_client::models::CreateWorkspaceRequest {
            name: name.to_string(),
        };
        let response = workspaces_api::create_workspace(self.client.data_config(), body).await?;
        Ok(response.id.to_string())
    }

    pub async fn update_workspace(&self, workspace_id: &str, name: &str) -> Result<String> {
        let body = crate::doqium_data_client::models::CreateWorkspaceRequest {
            name: name.to_string(),
        };
        let response =
            workspaces_api::update_wprkspace(self.client.data_config(), workspace_id, body).await?;
        Ok(response.id.to_string())
    }

    pub async fn delete_workspace(&self, workspace_id: &str) -> Result<()> {
        workspaces_api::delete_workspace(self.client.data_config(), workspace_id).await?;
        Ok(())
    }

    pub async fn list_notebooks(&self) -> Result<Vec<Notebook>> {
        let notebooks = notebooks_api::list_notebooks(self.client.data_config()).await?;
        Ok(notebooks)
    }

    pub async fn create_notebook(&self, workspace_id: &str, name: &str) -> Result<String> {
        let workspace_uuid = Uuid::parse_str(workspace_id)?;
        let body = crate::doqium_data_client::models::CreateNotebookRequest {
            workspace_id: workspace_uuid,
            name: name.to_string(),
        };
        let response = notebooks_api::create_notebook(self.client.data_config(), body).await?;
        Ok(response.id.to_string())
    }

    pub async fn update_notebook(&self, notebook_id: &str, name: &str) -> Result<String> {
        let body = crate::doqium_data_client::models::CreateWorkspaceRequest {
            name: name.to_string(),
        };
        let response =
            notebooks_api::update_notebook(self.client.data_config(), notebook_id, body).await?;
        Ok(response.id.to_string())
    }

    pub async fn delete_notebook(&self, notebook_id: &str) -> Result<()> {
        notebooks_api::delete_notebook(self.client.data_config(), notebook_id).await?;
        Ok(())
    }

    pub async fn list_notes(&self, notebook_id: &str) -> Result<Vec<Note>> {
        let notes = notes_api::list_notes(self.client.data_config(), notebook_id).await?;
        Ok(notes)
    }

    pub async fn get_note(&self, notebook_id: &str, note_id: &str) -> Result<Note> {
        let note = notes_api::get_note(self.client.data_config(), notebook_id, note_id).await?;
        Ok(note)
    }

    pub async fn create_note(
        &self,
        notebook_id: &str,
        note_request: crate::doqium_data_client::models::NoteRequest,
    ) -> Result<String> {
        let response =
            notes_api::create_note(self.client.data_config(), notebook_id, note_request).await?;
        Ok(response.id.to_string())
    }

    pub async fn update_note(
        &self,
        notebook_id: &str,
        note_id: &str,
        note_request: crate::doqium_data_client::models::NoteRequest,
    ) -> Result<()> {
        notes_api::update_note(
            self.client.data_config(),
            notebook_id,
            note_id,
            note_request,
        )
        .await?;
        Ok(())
    }

    pub async fn delete_note(&self, notebook_id: &str, note_id: &str) -> Result<()> {
        notes_api::delete_note(self.client.data_config(), notebook_id, note_id).await?;
        Ok(())
    }

    pub async fn get_stats(&self) -> Result<serde_json::Value> {
        let stats =
            crate::doqium_data_client::apis::admin_api::admin_data_stats(self.client.data_config())
                .await?;
        Ok(stats)
    }
}
