use indieweb::http::Client;
use indieweb::standards::indieauth::AccessToken;
use indieweb::standards::micropub::query::{Query, QueryKind, ConfigurationResponse, Response};
use serde::Serialize;
use url::Url;

#[derive(Serialize)]
pub struct ConfigResult {
    pub endpoint: String,
    pub media_endpoint: Option<String>,
    pub post_types: Vec<String>,
    pub categories: Vec<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub syndicate_to: Option<Vec<String>>,
}

pub async fn run(
    client: &impl Client,
    endpoint: &Url,
    access_token: Option<&AccessToken>,
) -> miette::Result<ConfigResult> {
    let query = Query {
        pagination: Default::default(),
        kind: QueryKind::Configuration,
    };

    let response = if let Some(token) = access_token {
        query.send(client, endpoint, token).await?
    } else {
        let http_client = indieweb::http::reqwest::Client::default();
        let anon_token = AccessToken::new("");
        query.send(&http_client, endpoint, &anon_token).await?
    };

    let config = match response {
        Response::Configuration(config) => config,
        Response::Error(e) => return Err(miette::miette!("Micropub error: {:?}", e)),
        _ => return Err(miette::miette!("Unexpected response type")),
    };

    Ok(ConfigResult {
        endpoint: endpoint.to_string(),
        media_endpoint: config.media_endpoint.map(|u| u.to_string()),
        post_types: config.post_types.iter().map(|pt| {
            match pt {
                indieweb::standards::micropub::query::PostTypeInfo::Simple(t) => t.to_string(),
                indieweb::standards::micropub::query::PostTypeInfo::Extended { name, .. } => name.clone(),
            }
        }).collect(),
        categories: config.category,
        syndicate_to: None,
    })
}
