// Code generated by oagen. DO NOT EDIT.

use crate::client::Retab;
#[allow(unused_imports)]
use crate::enums::*;
use crate::error::Error;
#[allow(unused_imports)]
use crate::models::*;
use crate::resources::workflow_artifacts::WorkflowArtifactsApi;
use crate::resources::workflow_blocks::WorkflowBlocksApi;
use crate::resources::workflow_edges::WorkflowEdgesApi;
use crate::resources::workflow_evals::WorkflowEvalsApi;
use crate::resources::workflow_experiments::WorkflowExperimentsApi;
use crate::resources::workflow_reviews::WorkflowReviewsApi;
use crate::resources::workflow_runs::WorkflowRunsApi;
use crate::resources::workflow_spec::WorkflowSpecApi;
use crate::resources::workflow_steps::WorkflowStepsApi;
#[allow(unused_imports)]
use serde::Serialize;

pub struct WorkflowsApi<'a> {
    pub(crate) client: &'a Retab,
}

#[derive(Debug, Clone, Serialize)]
pub struct ListParams {
    #[serde(skip_serializing_if = "Option::is_none")]
    pub before: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub after: Option<String>,
    /// Items per page
    ///
    /// Defaults to `10`.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub limit: Option<i64>,
    /// Defaults to `desc`.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub order: Option<WorkflowsOrder>,
    /// Defaults to `updated_at`.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub sort_by: Option<String>,
    /// Only return workflows belonging to this project. Use the shared project's id to list the organization's shared workflows.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub project_id: Option<String>,
}

impl Default for ListParams {
    #[allow(deprecated)]
    fn default() -> Self {
        Self {
            before: Default::default(),
            after: Default::default(),
            limit: Some(10),
            order: Some(WorkflowsOrder::Desc),
            sort_by: Some("updated_at".to_string()),
            project_id: Default::default(),
        }
    }
}

#[derive(Debug, Clone, Serialize)]
pub struct CreateParams {
    /// Request body sent with this call.
    ///
    /// Required.
    #[serde(skip)]
    pub body: CreateWorkflowRequest,
}

impl CreateParams {
    /// Construct a new `CreateParams` with the required fields set.
    #[allow(deprecated)]
    pub fn new(body: CreateWorkflowRequest) -> Self {
        Self { body }
    }
}

#[derive(Debug, Clone, Serialize)]
pub struct ApplyParams {
    /// Request body sent with this call.
    ///
    /// Required.
    #[serde(skip)]
    pub body: DeclarativeWorkflowRequest,
    /// Optional `workflow_id` selector. When `Some`, the call targets
    /// `/v1/workflows/{workflow_id}/spec/apply`; when `None`, the base `/v1/workflows/spec/apply` route.
    ///
    /// URL-only — never serialized into the request body.
    #[serde(skip)]
    pub workflow_id: Option<String>,
}

impl ApplyParams {
    /// Construct a new `ApplyParams` with the required fields set.
    #[allow(deprecated)]
    pub fn new(body: DeclarativeWorkflowRequest) -> Self {
        Self {
            body,
            workflow_id: Default::default(),
        }
    }
}

#[derive(Debug, Clone, Serialize)]
pub struct PlanParams {
    /// Request body sent with this call.
    ///
    /// Required.
    #[serde(skip)]
    pub body: DeclarativeWorkflowRequest,
    /// Optional `workflow_id` selector. When `Some`, the call targets
    /// `/v1/workflows/{workflow_id}/spec/plan`; when `None`, the base `/v1/workflows/spec/plan` route.
    ///
    /// URL-only — never serialized into the request body.
    #[serde(skip)]
    pub workflow_id: Option<String>,
}

impl PlanParams {
    /// Construct a new `PlanParams` with the required fields set.
    #[allow(deprecated)]
    pub fn new(body: DeclarativeWorkflowRequest) -> Self {
        Self {
            body,
            workflow_id: Default::default(),
        }
    }
}

#[derive(Debug, Clone, Serialize)]
pub struct ListVersionsParams {
    /// Workflow whose versions to list
    ///
    /// Required.
    pub workflow_id: String,
    /// Workflow version cursor before
    #[serde(skip_serializing_if = "Option::is_none")]
    pub before: Option<String>,
    /// Workflow version cursor after
    #[serde(skip_serializing_if = "Option::is_none")]
    pub after: Option<String>,
    /// Maximum number of versions to return
    ///
    /// Defaults to `50`.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub limit: Option<i64>,
}

impl ListVersionsParams {
    /// Construct a new `ListVersionsParams` with the required fields set.
    #[allow(deprecated)]
    pub fn new(workflow_id: impl Into<String>) -> Self {
        Self {
            workflow_id: workflow_id.into(),
            before: Default::default(),
            after: Default::default(),
            limit: Some(50),
        }
    }
}

#[derive(Debug, Clone, Serialize)]
pub struct ListDiffParams {
    /// Workflow whose versions to diff
    ///
    /// Required.
    pub workflow_id: String,
    /// Base workflow version ID
    ///
    /// Required.
    pub from_workflow_version_id: String,
    /// Target workflow version ID
    ///
    /// Required.
    pub to_workflow_version_id: String,
}

impl ListDiffParams {
    /// Construct a new `ListDiffParams` with the required fields set.
    #[allow(deprecated)]
    pub fn new(
        workflow_id: impl Into<String>,
        from_workflow_version_id: impl Into<String>,
        to_workflow_version_id: impl Into<String>,
    ) -> Self {
        Self {
            workflow_id: workflow_id.into(),
            from_workflow_version_id: from_workflow_version_id.into(),
            to_workflow_version_id: to_workflow_version_id.into(),
        }
    }
}

#[derive(Debug, Clone, Serialize)]
pub struct GetVersionParams {
    /// Workflow that owns the version. Workflow version ids are content-addressed by executable spec, so workflow_id disambiguates identical specs reused across workflows.
    ///
    /// Required.
    pub workflow_id: String,
}

impl GetVersionParams {
    /// Construct a new `GetVersionParams` with the required fields set.
    #[allow(deprecated)]
    pub fn new(workflow_id: impl Into<String>) -> Self {
        Self {
            workflow_id: workflow_id.into(),
        }
    }
}

#[derive(Debug, Clone, Serialize)]
pub struct CreateVersionRestoreParams {
    /// Workflow to restore into a new draft
    ///
    /// Required.
    pub workflow_id: String,
}

impl CreateVersionRestoreParams {
    /// Construct a new `CreateVersionRestoreParams` with the required fields set.
    #[allow(deprecated)]
    pub fn new(workflow_id: impl Into<String>) -> Self {
        Self {
            workflow_id: workflow_id.into(),
        }
    }
}

#[derive(Debug, Clone, Serialize)]
pub struct UpdateParams {
    /// Request body sent with this call.
    ///
    /// Required.
    #[serde(skip)]
    pub body: UpdateWorkflowRequest,
}

impl UpdateParams {
    /// Construct a new `UpdateParams` with the required fields set.
    #[allow(deprecated)]
    pub fn new(body: UpdateWorkflowRequest) -> Self {
        Self { body }
    }
}

#[derive(Debug, Clone, Default, Serialize)]
pub struct PublishParams {
    /// Request body sent with this call.
    #[serde(skip)]
    pub body: Option<PublishWorkflowRequest>,
}

impl<'a> WorkflowsApi<'a> {
    /// Access the `artifacts` sub-resource.
    pub fn artifacts(&self) -> WorkflowArtifactsApi<'a> {
        WorkflowArtifactsApi {
            client: self.client,
        }
    }

    /// Access the `blocks` sub-resource.
    pub fn blocks(&self) -> WorkflowBlocksApi<'a> {
        WorkflowBlocksApi {
            client: self.client,
        }
    }

    /// Access the `edges` sub-resource.
    pub fn edges(&self) -> WorkflowEdgesApi<'a> {
        WorkflowEdgesApi {
            client: self.client,
        }
    }

    /// Access the `evals` sub-resource.
    pub fn evals(&self) -> WorkflowEvalsApi<'a> {
        WorkflowEvalsApi {
            client: self.client,
        }
    }

    /// Access the `experiments` sub-resource.
    pub fn experiments(&self) -> WorkflowExperimentsApi<'a> {
        WorkflowExperimentsApi {
            client: self.client,
        }
    }

    /// Access the `reviews` sub-resource.
    pub fn reviews(&self) -> WorkflowReviewsApi<'a> {
        WorkflowReviewsApi {
            client: self.client,
        }
    }

    /// Access the `runs` sub-resource.
    pub fn runs(&self) -> WorkflowRunsApi<'a> {
        WorkflowRunsApi {
            client: self.client,
        }
    }

    /// Access the `spec` sub-resource.
    pub fn spec(&self) -> WorkflowSpecApi<'a> {
        WorkflowSpecApi {
            client: self.client,
        }
    }

    /// Access the `steps` sub-resource.
    pub fn steps(&self) -> WorkflowStepsApi<'a> {
        WorkflowStepsApi {
            client: self.client,
        }
    }

    /// List Workflows
    ///
    /// List workflows with pagination and optional filtering.
    pub async fn list(&self, params: ListParams) -> Result<WorkflowList, Error> {
        self.list_with_options(params, None).await
    }

    /// Variant of [`Self::list`] that accepts per-request [`crate::RequestOptions`].
    pub async fn list_with_options(
        &self,
        params: ListParams,
        options: Option<&crate::RequestOptions>,
    ) -> Result<WorkflowList, Error> {
        let path = "/v1/workflows".to_string();
        let method = http::Method::GET;
        self.client
            .request_page(method, &path, &params, "after", options)
            .await
    }

    /// Create Workflow
    ///
    /// Create a new workflow.
    ///
    /// The workflow starts unpublished with a default "Document" input block.
    pub async fn create(&self, params: CreateParams) -> Result<Workflow, Error> {
        self.create_with_options(params, None).await
    }

    /// Variant of [`Self::create`] that accepts per-request [`crate::RequestOptions`].
    pub async fn create_with_options(
        &self,
        params: CreateParams,
        options: Option<&crate::RequestOptions>,
    ) -> Result<Workflow, Error> {
        let path = "/v1/workflows".to_string();
        let method = http::Method::POST;
        self.client
            .request_with_body_opts(method, &path, &params, Some(&params.body), options)
            .await
    }

    /// Apply Workflow Spec
    ///
    /// Create a new workflow from a declarative YAML spec.
    ///
    /// The workflow id in the YAML is treated as source context, not as the target
    /// workflow id. Use `POST /v1/workflows/{workflow_id}/spec/apply` to modify an
    /// existing workflow draft.
    pub async fn apply(&self, params: ApplyParams) -> Result<DeclarativeApplyResponse, Error> {
        self.apply_with_options(params, None).await
    }

    /// Variant of [`Self::apply`] that accepts per-request [`crate::RequestOptions`].
    pub async fn apply_with_options(
        &self,
        params: ApplyParams,
        options: Option<&crate::RequestOptions>,
    ) -> Result<DeclarativeApplyResponse, Error> {
        let path = if let Some(workflow_id) = params.workflow_id.as_ref() {
            let workflow_id = crate::client::path_segment(workflow_id);
            format!("/v1/workflows/{workflow_id}/spec/apply")
        } else {
            "/v1/workflows/spec/apply".to_string()
        };
        let method = http::Method::POST;
        self.client
            .request_with_body_opts(method, &path, &params, Some(&params.body), options)
            .await
    }

    /// Plan Workflow Spec
    ///
    /// Preview the changes a declarative YAML spec would make to the draft workflow.
    ///
    /// Compares the spec against the current draft and returns the resulting
    /// changes without applying them. A spec that already matches the draft
    /// plans as a no-op.
    pub async fn plan(&self, params: PlanParams) -> Result<DeclarativePlanResponse, Error> {
        self.plan_with_options(params, None).await
    }

    /// Variant of [`Self::plan`] that accepts per-request [`crate::RequestOptions`].
    pub async fn plan_with_options(
        &self,
        params: PlanParams,
        options: Option<&crate::RequestOptions>,
    ) -> Result<DeclarativePlanResponse, Error> {
        let path = if let Some(workflow_id) = params.workflow_id.as_ref() {
            let workflow_id = crate::client::path_segment(workflow_id);
            format!("/v1/workflows/{workflow_id}/spec/plan")
        } else {
            "/v1/workflows/spec/plan".to_string()
        };
        let method = http::Method::POST;
        self.client
            .request_with_body_opts(method, &path, &params, Some(&params.body), options)
            .await
    }

    /// List Workflow Versions
    pub async fn list_versions(
        &self,
        params: ListVersionsParams,
    ) -> Result<WorkflowGraphVersionList, Error> {
        self.list_versions_with_options(params, None).await
    }

    /// Variant of [`Self::list_versions`] that accepts per-request [`crate::RequestOptions`].
    pub async fn list_versions_with_options(
        &self,
        params: ListVersionsParams,
        options: Option<&crate::RequestOptions>,
    ) -> Result<WorkflowGraphVersionList, Error> {
        let path = "/v1/workflows/versions".to_string();
        let method = http::Method::GET;
        self.client
            .request_page(method, &path, &params, "after", options)
            .await
    }

    /// Diff Workflow Versions
    pub async fn list_diff(
        &self,
        params: ListDiffParams,
    ) -> Result<WorkflowGraphVersionDiff, Error> {
        self.list_diff_with_options(params, None).await
    }

    /// Variant of [`Self::list_diff`] that accepts per-request [`crate::RequestOptions`].
    pub async fn list_diff_with_options(
        &self,
        params: ListDiffParams,
        options: Option<&crate::RequestOptions>,
    ) -> Result<WorkflowGraphVersionDiff, Error> {
        let path = "/v1/workflows/versions/diff".to_string();
        let method = http::Method::GET;
        self.client
            .request_with_query_opts(method, &path, &params, options)
            .await
    }

    /// Get Workflow Version
    pub async fn get_version(
        &self,
        workflow_version_id: &str,
        params: GetVersionParams,
    ) -> Result<WorkflowGraphVersion, Error> {
        self.get_version_with_options(workflow_version_id, params, None)
            .await
    }

    /// Variant of [`Self::get_version`] that accepts per-request [`crate::RequestOptions`].
    pub async fn get_version_with_options(
        &self,
        workflow_version_id: &str,
        params: GetVersionParams,
        options: Option<&crate::RequestOptions>,
    ) -> Result<WorkflowGraphVersion, Error> {
        let workflow_version_id = crate::client::path_segment(workflow_version_id);
        let path = format!("/v1/workflows/versions/{workflow_version_id}");
        let method = http::Method::GET;
        self.client
            .request_with_query_opts(method, &path, &params, options)
            .await
    }

    /// Restore Workflow Version
    pub async fn create_version_restore(
        &self,
        workflow_version_id: &str,
        params: CreateVersionRestoreParams,
    ) -> Result<Workflow, Error> {
        self.create_version_restore_with_options(workflow_version_id, params, None)
            .await
    }

    /// Variant of [`Self::create_version_restore`] that accepts per-request [`crate::RequestOptions`].
    pub async fn create_version_restore_with_options(
        &self,
        workflow_version_id: &str,
        params: CreateVersionRestoreParams,
        options: Option<&crate::RequestOptions>,
    ) -> Result<Workflow, Error> {
        let workflow_version_id = crate::client::path_segment(workflow_version_id);
        let path = format!("/v1/workflows/versions/{workflow_version_id}/restore");
        let method = http::Method::POST;
        self.client
            .request_with_query_opts(method, &path, &params, options)
            .await
    }

    /// Get Workflow
    ///
    /// Get a single workflow by ID.
    ///
    /// Returns workflow metadata only.
    pub async fn get(&self, workflow_id: &str) -> Result<Workflow, Error> {
        self.get_with_options(workflow_id, None).await
    }

    /// Variant of [`Self::get`] that accepts per-request [`crate::RequestOptions`].
    pub async fn get_with_options(
        &self,
        workflow_id: &str,
        options: Option<&crate::RequestOptions>,
    ) -> Result<Workflow, Error> {
        let workflow_id = crate::client::path_segment(workflow_id);
        let path = format!("/v1/workflows/{workflow_id}");
        let method = http::Method::GET;
        self.client
            .request_with_query_opts(method, &path, &(), options)
            .await
    }

    /// Update Workflow
    ///
    /// Update an existing workflow.
    pub async fn update(&self, workflow_id: &str, params: UpdateParams) -> Result<Workflow, Error> {
        self.update_with_options(workflow_id, params, None).await
    }

    /// Variant of [`Self::update`] that accepts per-request [`crate::RequestOptions`].
    pub async fn update_with_options(
        &self,
        workflow_id: &str,
        params: UpdateParams,
        options: Option<&crate::RequestOptions>,
    ) -> Result<Workflow, Error> {
        let workflow_id = crate::client::path_segment(workflow_id);
        let path = format!("/v1/workflows/{workflow_id}");
        let method = http::Method::PATCH;
        self.client
            .request_with_body_opts(method, &path, &params, Some(&params.body), options)
            .await
    }

    /// Delete Workflow
    ///
    /// Delete a workflow and all its associated entities.
    ///
    /// This deletes the workflow, all of its blocks and edges, and all of their
    /// snapshots.
    pub async fn delete(&self, workflow_id: &str) -> Result<(), Error> {
        self.delete_with_options(workflow_id, None).await
    }

    /// Variant of [`Self::delete`] that accepts per-request [`crate::RequestOptions`].
    pub async fn delete_with_options(
        &self,
        workflow_id: &str,
        options: Option<&crate::RequestOptions>,
    ) -> Result<(), Error> {
        let workflow_id = crate::client::path_segment(workflow_id);
        let path = format!("/v1/workflows/{workflow_id}");
        let method = http::Method::DELETE;
        self.client
            .request_with_query_opts_empty(method, &path, &(), options)
            .await
    }

    /// Discard Draft Workflow
    ///
    /// Discard all draft changes and restore the workflow to its published state.
    ///
    /// The workflow must already be published.
    pub async fn discard_draft(&self, workflow_id: &str) -> Result<Workflow, Error> {
        self.discard_draft_with_options(workflow_id, None).await
    }

    /// Variant of [`Self::discard_draft`] that accepts per-request [`crate::RequestOptions`].
    pub async fn discard_draft_with_options(
        &self,
        workflow_id: &str,
        options: Option<&crate::RequestOptions>,
    ) -> Result<Workflow, Error> {
        let workflow_id = crate::client::path_segment(workflow_id);
        let path = format!("/v1/workflows/{workflow_id}/discard-draft");
        let method = http::Method::POST;
        self.client
            .request_with_query_opts(method, &path, &(), options)
            .await
    }

    /// Publish Workflow
    ///
    /// Publish a workflow.
    ///
    /// This creates an immutable snapshot of the workflow configuration, making it available for workflow runs.
    /// The live entities remain unchanged so users can continue editing.
    pub async fn publish(
        &self,
        workflow_id: &str,
        params: PublishParams,
    ) -> Result<Workflow, Error> {
        self.publish_with_options(workflow_id, params, None).await
    }

    /// Variant of [`Self::publish`] that accepts per-request [`crate::RequestOptions`].
    pub async fn publish_with_options(
        &self,
        workflow_id: &str,
        params: PublishParams,
        options: Option<&crate::RequestOptions>,
    ) -> Result<Workflow, Error> {
        let workflow_id = crate::client::path_segment(workflow_id);
        let path = format!("/v1/workflows/{workflow_id}/publish");
        let method = http::Method::POST;
        self.client
            .request_with_body_opts(method, &path, &params, params.body.as_ref(), options)
            .await
    }
}
