use anyhow::{Context, Result};
use serde_json::{json, Value};

use super::auth;
use super::token;
use crate::xrpc::XrpcClient;

const CHAT_PROXY_HEADER: &str = "did:web:bsky.syu.is#bsky_chat";

/// Load chat proxy DID from config or use default
fn load_chat_proxy() -> Result<String> {
    let config = token::load_config()?;
    if let Some(network) = config["network"].as_str() {
        Ok(format!("did:web:bsky.{}#bsky_chat", network))
    } else {
        Ok(CHAT_PROXY_HEADER.to_string())
    }
}

/// Send a DM via chat.bsky.convo.sendMessage
pub async fn post(text: &str, is_bot: bool, did: &str) -> Result<()> {
    let session = if is_bot {
        auth::refresh_bot_session().await?
    } else {
        auth::refresh_session().await?
    };
    let pds = session.pds.as_deref().unwrap_or("syu.is");
    let client = if is_bot {
        XrpcClient::new_bot(pds)
    } else {
        XrpcClient::new(pds)
    };
    let proxy = load_chat_proxy()?;

    // Get or create convo with the target DID
    let convo_resp: Value = client
        .query_auth_proxy(
            "chat.bsky.convo.getConvoForMembers",
            &[("members", did)],
            &session.access_jwt,
            &proxy,
        )
        .await
        .context("Failed to get convo for members")?;

    let convo_id = convo_resp["convo"]["id"]
        .as_str()
        .context("No convo id in response")?;

    // Send message
    let send_body = json!({
        "convoId": convo_id,
        "message": {
            "text": text
        }
    });

    let result: Value = client
        .call_proxy(
            "chat.bsky.convo.sendMessage",
            &send_body,
            &session.access_jwt,
            &proxy,
        )
        .await
        .context("Failed to send message")?;

    let msg_id = result["id"].as_str().unwrap_or("unknown");
    println!("{}", json!({
        "id": msg_id,
        "convoId": convo_id,
    }));

    Ok(())
}
