use reqwest::Client;

use crate::{
    configuration::CONFIGURATION,
    types::{CallArguments, ClientCommands},
};

pub async fn run_client(
    arguments: &CallArguments,
) -> Result<(), Box<dyn std::error::Error + 'static>> {
    if arguments.server {
        eprintln!("Server mode is enabled, but this is a client function.");
        return Err("Server mode cannot be used in client context".into());
    }
    if arguments.client_commands.is_none() {
        eprintln!("No client command provided.");
        return Err("No client command provided".into());
    }

    match arguments.client_commands.as_ref().unwrap() {
        ClientCommands::Add { name } => _add(name).await,
        ClientCommands::Get { id_or_name } => _get(id_or_name).await,
    }
}

fn _get_url(sub_path: &str, id: &str) -> String {
    let config = CONFIGURATION.get().unwrap();

    let mut url = format!("http://{}:{}", config.server.host, config.server.port);

    if !sub_path.is_empty() {
        if sub_path.starts_with('/') {
            url.push_str(sub_path);
        } else {
            url.push('/');
            url.push_str(sub_path);
        }
    }

    if url.ends_with('/') && !id.is_empty() {
        url = url[..url.len() - 1].to_string();
    }

    if !id.is_empty() {
        if !id.starts_with("/") {
            url.push('/');
        }

        url.push_str(id);
    }

    url
}

async fn _get(_id_or_name: &str) -> Result<(), Box<dyn std::error::Error + 'static>> {
    let url = _get_url("resource", _id_or_name);

    let parsed_url = url::Url::parse(&url);

    if parsed_url.is_err() {
        eprintln!("Invalid URL: {}", url);
        return Err(format!("Invalid URL: {}", url).into());
    }

    let parsed_url = parsed_url.unwrap();

    let client = Client::builder()
        .danger_accept_invalid_certs(true)
        .build()
        .unwrap_or_default();

    let response = client.get(parsed_url.as_str()).send().await;

    match response {
        Ok(resp) => {
            println!(
                "StatusCode: {} {}",
                resp.status(),
                resp.status().is_success()
            );
            resp.status().is_success();
        }
        Err(err) => {
            println!("code:{},error:{}", err.status().unwrap_or_default(), err);
        }
    }
    Ok(())
}

async fn _add(name: &str) -> Result<(), Box<dyn std::error::Error + 'static>> {
    let url = _get_url("resource", name);

    let parsed_url = url::Url::parse(&url);

    if parsed_url.is_err() {
        eprintln!("Invalid URL: {}", url);
        return Err(format!("Invalid URL: {}", url).into());
    }

    let parsed_url = parsed_url.unwrap();

    let client = Client::builder()
        .danger_accept_invalid_certs(true)
        .build()
        .unwrap_or_default();

    let response = client.post(parsed_url.as_str()).send().await;

    match response {
        Ok(resp) => {
            println!(
                "StatusCode: {} {}\n=>{}",
                resp.status(),
                resp.status().is_success(),
                resp.text().await.unwrap_or_default()
            );
        }
        Err(err) => {
            println!("code:{},error:{}", err.status().unwrap_or_default(), err);
        }
    }
    Ok(())
}
