use crate::data_struct::ica::messages::{DeleteMessage, SendMessage};
use crate::error::{ClientResult, IcaError};
use crate::MainStatus;

use colored::Colorize;
use ed25519_dalek::{Signature, Signer, SigningKey};
use rust_socketio::asynchronous::Client;
use rust_socketio::Payload;
use serde_json::Value;
use tracing::{debug, info, span, warn, Level};

/// "安全" 的 发送一条消息
pub async fn send_message(client: &Client, message: &SendMessage) -> bool {
    let value = message.as_value();
    match client.emit("sendMessage", value).await {
        Ok(_) => {
            debug!("send_message {}", format!("{:#?}", message).cyan());
            true
        }
        Err(e) => {
            warn!("send_message faild:{}", format!("{:#?}", e).red());
            false
        }
    }
}
/// "安全" 的 删除一条消息
pub async fn delete_message(client: &Client, message: &DeleteMessage) -> bool {
    let value = message.as_value();
    match client.emit("deleteMessage", value).await {
        Ok(_) => {
            debug!("delete_message {}", format!("{:#?}", message).yellow());
            true
        }
        Err(e) => {
            warn!("delete_message faild:{}", format!("{:#?}", e).red());
            false
        }
    }
}
/// "安全" 的 获取历史消息
/// ```typescript
/// async fetchHistory(messageId: string, roomId: number, currentLoadedMessagesCount: number)
/// ```
// #[allow(dead_code)]
// pub async fn fetch_history(client: &Client, roomd_id: RoomId) -> bool { false }

async fn inner_sign(payload: Payload, client: Client) -> ClientResult<(), IcaError> {
    let span = span!(Level::INFO, "signing icalingua");
    let _guard = span.enter();

    // 获取数据
    let require_data = match payload {
        Payload::Text(json_value) => Ok(json_value),
        _ => Err(IcaError::LoginFailed("Got a invalid payload".to_string())),
    }?;

    let (auth_key, version) = (&require_data[0], &require_data[1]);

    info!("auth_key: {:?}, server_version: {:?}", auth_key, version);
    // 判定和自己的兼容版本号是否 一致
    let server_protocol_version = version
        .get("protocolVersion")
        .unwrap_or(&Value::Null)
        .as_str()
        .unwrap_or("unknow");
    if server_protocol_version != crate::ica::ICA_PROTOCOL_VERSION {
        warn!(
            "服务器版本与兼容版本不一致\n服务器协议版本:{:?}\n兼容版本:{}",
            version.get("protocolVersion"),
            crate::ica::ICA_PROTOCOL_VERSION
        );
    }

    let auth_key = match &require_data.first() {
        Some(Value::String(auth_key)) => Ok(auth_key),
        _ => Err(IcaError::LoginFailed("Got a invalid auth_key".to_string())),
    }?;

    let salt = hex::decode(auth_key).expect("Got an invalid salt from the server");
    // 签名
    let private_key = MainStatus::global_config().ica().private_key.clone();

    let array_key: [u8; 32] = hex::decode(private_key)
        .expect("Not a vaild pub key")
        .try_into()
        .expect("Not a vaild pub key");
    let signing_key: SigningKey = SigningKey::from_bytes(&array_key);
    let signature: Signature = signing_key.sign(salt.as_slice());

    // 发送签名
    let sign = signature.to_bytes().to_vec();
    client.emit("auth", sign).await.expect("Faild to send signin data");
    Ok(())
}

/// 签名回调
/// 失败的时候得 panic
pub async fn sign_callback(payload: Payload, client: Client) {
    inner_sign(payload, client).await.expect("Faild to sign");
}
