use cloudflare::endpoints::workerskv::WorkersKvNamespace;
use cloudflare::framework::response::ApiFailure;

use anyhow::Result;

use crate::http;
use crate::settings::global_user::GlobalUser;
use crate::settings::toml::Target;

use super::create;
use super::list;

pub enum UpsertedNamespace {
    Created(WorkersKvNamespace),
    Reused(WorkersKvNamespace),
}

pub fn upsert(target: &Target, user: &GlobalUser, title: String) -> Result<UpsertedNamespace> {
    let client = http::cf_v4_client(user)?;
    let response = create(&client, target.account_id.load()?, &title);

    match response {
        Ok(success) => Ok(UpsertedNamespace::Created(success.result)),
        Err(e) => match &e {
            ApiFailure::Error(_status, api_errors) => {
                if api_errors.errors.iter().any(|e| e.code == 10014) {
                    log::info!("Namespace {} already exists.", title);

                    match list(&client, target)?
                        .iter()
                        .find(|ns| ns.title == title) {
                        Some(namespace) => Ok(UpsertedNamespace::Reused(namespace.to_owned())),
                        None => anyhow::bail!("namespace already exists, but could not be found in the API's listed namespaces"),
                    }
                } else {
                    anyhow::bail!("{}", http::format_error(e, Some(&error_suggestions)))
                }
            }
            _ => anyhow::bail!("{}", http::format_error(e, Some(&error_suggestions))),
        },
    }
}

fn error_suggestions(code: u16) -> &'static str {
    match code {
        10014 => "Namespace already exists, try using a different namespace.",
        10037 => "Edit your API Token to have correct permissions, or use the 'Edit Cloudflare Workers' API Token template.",
        _ => "",
    }
}
