use crate::errors::KamError;
use std::fs;
use std::path::PathBuf;

use x509_parser::prelude::*;

// 获取信任的根CA证书目录
// 在 KAM_HOME（默认：~/.kam）/trusted-cas 下
fn trusted_cas_dir() -> Result<PathBuf, KamError> {
    let base = crate::utils::kam_home_dir()?;
    let dir = base.join("trusted-cas");
    if !dir.exists() {
        fs::create_dir_all(&dir).map_err(KamError::Io)?;
    }
    Ok(dir)
}

// 获取缓存的证书目录
fn certs_dir() -> Result<PathBuf, KamError> {
    let base = crate::utils::kam_home_dir()?;
    let dir = base.join("certs");
    if !dir.exists() {
        fs::create_dir_all(&dir).map_err(KamError::Io)?;
    }
    Ok(dir)
}

// 加载所有信任的根CA证书（PEM格式字符串）
pub fn load_trusted_cas() -> Result<Vec<String>, KamError> {
    let dir = trusted_cas_dir()?;
    let mut cas = Vec::new();

    for entry in fs::read_dir(&dir).map_err(KamError::Io)? {
        let entry = entry.map_err(KamError::Io)?;
        let path = entry.path();

        if path.extension().and_then(|s| s.to_str()) == Some("pem") {
            let pem_data = fs::read_to_string(&path).map_err(KamError::Io)?;
            // 验证一下确实是有效的证书（虽然可能有点慢，但安全第一）
            parse_x509_pem_certificate(&pem_data)?;
            cas.push(pem_data);
        }
    }

    Ok(cas)
}

// 添加一个根CA到信任列表
// 会验证证书格式，然后保存为 {name}.pem
// TODO: 也许应该检查一下名字是否合法？不过暂时先这样
pub fn add_trusted_ca(pem: &str, name: &str) -> Result<(), KamError> {
    let dir = trusted_cas_dir()?;

    // 先验证证书格式（不然存个无效的证书也没用）
    parse_x509_pem_certificate(pem)?;

    // 保存到文件，简单粗暴
    let filename = format!("{}.pem", name);
    let path = dir.join(filename);
    fs::write(&path, pem).map_err(KamError::Io)?;

    Ok(())
}

// 列出所有信任的根CA及其指纹
pub fn list_trusted_cas() -> Result<Vec<(String, String)>, KamError> {
    let dir = trusted_cas_dir()?;
    let mut cas = Vec::new();

    for entry in fs::read_dir(&dir).map_err(KamError::Io)? {
        let entry = entry.map_err(KamError::Io)?;
        let path = entry.path();

        if path.extension().and_then(|s| s.to_str()) == Some("pem") {
            let name = path
                .file_stem()
                .and_then(|s| s.to_str())
                .unwrap_or("unknown")
                .to_string();

            let pem_data = fs::read_to_string(&path).map_err(KamError::Io)?;
            let fingerprint = calculate_fingerprint_from_pem(&pem_data)?;

            cas.push((name, fingerprint));
        }
    }

    Ok(cas)
}

// 从信任列表里删除一个根CA（根据名字）
pub fn remove_trusted_ca(name: &str) -> Result<(), KamError> {
    let dir = trusted_cas_dir()?;
    let filename = format!("{}.pem", name);
    let path = dir.join(filename);

    if path.exists() {
        fs::remove_file(&path).map_err(KamError::Io)?;
        Ok(())
    } else {
        Err(KamError::CommandFailed(format!(
            "Trusted CA '{}' not found",
            name
        )))
    }
}

// 从缓存加载证书链（根据名字）
pub fn load_cert_chain(name: &str) -> Result<String, KamError> {
    let dir = certs_dir()?;
    let filename = format!("{}.pem", name);
    let path = dir.join(filename);

    if !path.exists() {
        return Err(KamError::CommandFailed(format!(
            "Certificate '{}' not found",
            name
        )));
    }

    fs::read_to_string(&path).map_err(KamError::Io)
}

// 把证书链存到缓存里
pub fn store_cert_chain(name: &str, chain_pem: &str) -> Result<(), KamError> {
    let dir = certs_dir()?;

    // 先验证一下证书链格式
    parse_x509_pem_chain(chain_pem)?;

    let filename = format!("{}.pem", name);
    let path = dir.join(filename);
    fs::write(&path, chain_pem).map_err(KamError::Io)?;

    Ok(())
}

// 解析单个X.509证书（PEM格式），主要是为了验证格式
fn parse_x509_pem_certificate(pem: &str) -> Result<(), KamError> {
    let (_, pem_cert) = parse_x509_pem(pem.as_bytes())
        .map_err(|e| KamError::CommandFailed(format!("Failed to parse PEM: {}", e)))?;

    pem_cert.parse_x509().map_err(|e| {
        KamError::CommandFailed(format!("Failed to parse X.509 certificate: {}", e))
    })?;

    Ok(())
}

// 解析证书链（PEM格式），返回证书列表
// 会验证每个证书的格式
fn parse_x509_pem_chain(pem: &str) -> Result<(), KamError> {
    let mut remaining = pem.as_bytes();
    let mut count = 0;

    while let Ok((rest, pem_cert)) = parse_x509_pem(remaining) {
        pem_cert.parse_x509().map_err(|e| {
            KamError::CommandFailed(format!("Failed to parse X.509 certificate: {}", e))
        })?;
        count += 1;

        if rest.is_empty() {
            break;
        }
        remaining = rest;
    }

    if count == 0 {
        return Err(KamError::CommandFailed(
            crate::i18n::tr_key("secret.no_valid_cert_in_chain").to_string(),
        ));
    }

    Ok(())
}

// 验证证书链（对信任的CA）并提取公钥}
// 这个函数有点复杂，主要是处理证书链的验证逻辑
pub fn verify_cert_chain(chain_pem: &str, trusted_cas_pem: &[String]) -> Result<String, KamError> {
    // 先解析证书链，转成DER格式
    let mut der_blobs: Vec<Vec<u8>> = Vec::new();
    let mut remaining = chain_pem.as_bytes();

    while let Ok((rest, pem_cert)) = parse_x509_pem(remaining) {
        // 把DER内容复制到owned buffer，避免生命周期问题
        // Rust的ownership真是...不过这样更安全
        let der_vec = pem_cert.contents.to_vec();
        der_blobs.push(der_vec);

        if rest.is_empty() {
            break;
        }
        remaining = rest;
    }

    if der_blobs.is_empty() {
        return Err(KamError::CommandFailed(
            crate::i18n::tr_key("secret.no_valid_cert_in_chain").to_string(),
        ));
    }

    // 基本验证：检查issuer-subject关系
    // 每个证书的issuer应该等于下一个证书的subject
    for i in 0..der_blobs.len() - 1 {
        // 按需解析证书，避免borrow checker抱怨
        let (_, cert) = x509_parser::parse_x509_certificate(&der_blobs[i][..]).map_err(|e| {
            KamError::CommandFailed(format!("Failed to parse X.509 certificate: {}", e))
        })?;
        let (_, issuer_cert) =
            x509_parser::parse_x509_certificate(&der_blobs[i + 1][..]).map_err(|e| {
                KamError::CommandFailed(format!("Failed to parse X.509 certificate: {}", e))
            })?;

        if cert.issuer() != issuer_cert.subject() {
            return Err(KamError::CommandFailed(format!(
                "Certificate {} issuer does not match certificate {} subject",
                i,
                i + 1
            )));
        }
    }

    // 验证根证书是否在信任列表里
    // 根证书是链的最后一个
    let (_, root_cert) = x509_parser::parse_x509_certificate(&der_blobs[der_blobs.len() - 1][..])
        .map_err(|e| {
        KamError::CommandFailed(format!("Failed to parse X.509 certificate: {}", e))
    })?;
    let mut trusted = false;

    // 遍历所有信任的CA，看看有没有匹配的
    for ca_pem in trusted_cas_pem {
        let (_, ca_pem_cert) = parse_x509_pem(ca_pem.as_bytes())
            .map_err(|e| KamError::CommandFailed(format!("Failed to parse trusted CA: {}", e)))?;
        let ca_cert = ca_pem_cert.parse_x509().map_err(|e| {
            KamError::CommandFailed(format!("Failed to parse trusted CA certificate: {}", e))
        })?;

        if root_cert.tbs_certificate.as_ref() == ca_cert.tbs_certificate.as_ref() {
            trusted = true;
            break;
        }
    }

    if !trusted {
        return Err(KamError::CommandFailed(
            "Certificate chain root is not trusted".to_string(),
        ));
    }

    // 从终端实体证书（链的第一个）提取公钥
    let (_, end_entity) = x509_parser::parse_x509_certificate(&der_blobs[0][..]).map_err(|e| {
        KamError::CommandFailed(format!("Failed to parse X.509 certificate: {}", e))
    })?;
    extract_public_key_pem_from_cert(&end_entity)
}

// 从证书提取公钥，转成PEM格式
// 就是DER转base64，然后加上PEM的header/footer
fn extract_public_key_pem_from_cert(cert: &X509Certificate) -> Result<String, KamError> {
    let public_key = cert.public_key();
    let key_der = public_key.raw;

    // DER转base64
    use base64::engine::Engine as _;
    use base64::engine::general_purpose::STANDARD as BASE64_ENGINE;

    let b64 = BASE64_ENGINE.encode(key_der);
    let mut pem = String::from("-----BEGIN PUBLIC KEY-----\n");

    // 每64个字符一行（PEM标准）
    for chunk in b64.as_bytes().chunks(64) {
        pem.push_str(std::str::from_utf8(chunk).unwrap());
        pem.push('\n');
    }

    pem.push_str("-----END PUBLIC KEY-----\n");

    Ok(pem)
}

// 计算PEM证书的SHA-256指纹
// 就是算个hash，用来标识证书
fn calculate_fingerprint_from_pem(pem: &str) -> Result<String, KamError> {
    use sha2::{Digest, Sha256};

    let (_, pem_cert) = parse_x509_pem(pem.as_bytes())
        .map_err(|e| KamError::CommandFailed(format!("Failed to parse PEM: {}", e)))?;
    let cert = pem_cert
        .parse_x509()
        .map_err(|e| KamError::CommandFailed(format!("Failed to parse certificate: {}", e)))?;

    let mut hasher = Sha256::new();
    hasher.update(cert.tbs_certificate.as_ref());
    let result = hasher.finalize();
    Ok(hex::encode(result))
}
