use super::*;

pub(crate) fn validate_model_artifact(
    path: &Path,
    expected: ModelChoice,
    support: bool,
) -> Result<(), String> {
    if support {
        let model = Gguf::open(path)?;
        let shape = match expected {
            ModelChoice::DeepSeekV4Flash => FLASH,
            ModelChoice::DeepSeekV4Flash0731 => FLASH_0731,
            ModelChoice::DeepSeekV4Pro | ModelChoice::Glm52 => {
                return Err(format!("{expected} does not use an external support GGUF"));
            }
        };
        validate_support(&model, &shape).map(|_| ())
    } else {
        let model = Model::open_main(path, expected)?;
        let summary = model.summary();
        if summary.tensor_count == 0
            || model
                .render_prompt("", "", ReasoningMode::Direct)
                .is_empty()
        {
            return Err("model intake produced an empty tensor directory or prompt".into());
        }
        let _ = model.tokenize("");
        let eos = model.eos_token();
        let _ = model.token_bytes(eos);
        if !model.is_stop_token(eos) {
            return Err("tokenizer EOS marker is not a stop token".into());
        }
        model.tensor_data("token_embd.weight")?;
        Ok(())
    }
}

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub(super) enum SupportKind {
    LegacyMtp,
    DSpark,
}

#[derive(Clone, Debug, Eq, PartialEq)]
pub(super) struct DsparkConfig {
    pub(super) block_size: u32,
    pub(super) markov_rank: u32,
    pub(super) noise_token: u32,
    pub(super) target_layers: Vec<u32>,
    pub(super) stages: u32,
}

pub(super) fn dspark_config(model: &Gguf) -> Result<DsparkConfig, String> {
    let block_size = first_u32(
        model,
        &[
            "deepseek4.dspark.block_size",
            "deepseek4.dspark_block_size",
            "dspark.block_size",
        ],
    )?;
    let markov_rank = first_u32(
        model,
        &[
            "deepseek4.dspark.markov_rank",
            "deepseek4.dspark_markov_rank",
            "dspark.markov_rank",
        ],
    )?;
    let noise_token = first_u32(
        model,
        &[
            "deepseek4.dspark.noise_token_id",
            "deepseek4.dspark_noise_token_id",
            "dspark.noise_token_id",
        ],
    )?;
    let target_layers = first_u32s(
        model,
        &[
            "deepseek4.dspark.target_layer_ids",
            "deepseek4.dspark_target_layer_ids",
            "dspark.target_layer_ids",
        ],
    )?;
    let stages = model
        .tensors
        .keys()
        .filter_map(|name| {
            name.strip_prefix("mtp.")?
                .split('.')
                .next()?
                .parse::<u32>()
                .ok()
        })
        .max()
        .map_or(0, |stage| stage + 1);
    Ok(DsparkConfig {
        block_size,
        markov_rank,
        noise_token,
        target_layers: target_layers.to_vec(),
        stages,
    })
}

pub(super) fn validate_support(model: &Gguf, shape: &Shape) -> Result<SupportKind, String> {
    if model.tensors.contains_key("mtp.0.e_proj.weight")
        && model.tensors.contains_key("mtp.0.h_proj.weight")
        && model.tensors.contains_key("mtp.0.hc_head_base.weight")
    {
        validate_legacy_mtp(model, shape)?;
        Ok(SupportKind::LegacyMtp)
    } else if model.metadata.contains_key("deepseek4.dspark.block_size")
        || model.metadata.contains_key("deepseek4.dspark_block_size")
        || model.metadata.contains_key("dspark.block_size")
    {
        validate_dspark(model, shape)?;
        Ok(SupportKind::DSpark)
    } else {
        Err("support GGUF is neither legacy MTP nor DSpark".into())
    }
}

fn validate_legacy_mtp(model: &Gguf, shape: &Shape) -> Result<(), String> {
    if shape.model != ModelChoice::DeepSeekV4Flash {
        return Err("legacy MTP support is available only for DeepSeek V4 Flash".into());
    }
    let prefix = "mtp.0";
    let hc_dim = shape.embd * shape.hc;
    let hc_mix = 2 * shape.hc + shape.hc * shape.hc;
    let q_dim = shape.heads * shape.head_dim;
    let output_low = shape.out_groups * shape.lora_o;
    for (suffix, types, dims) in [
        ("hc_head_base.weight", &[F32][..], vec![shape.hc]),
        ("hc_head_fn.weight", PLAIN, vec![hc_dim, shape.hc]),
        ("hc_head_scale.weight", &[F32][..], vec![1]),
        ("e_proj.weight", &[Q8_0][..], vec![shape.embd, shape.embd]),
        ("h_proj.weight", &[Q8_0][..], vec![shape.embd, shape.embd]),
        ("enorm.weight", &[F32][..], vec![shape.embd]),
        ("hnorm.weight", &[F32][..], vec![shape.embd]),
        ("norm.weight", &[F32][..], vec![shape.embd]),
        ("hc_attn_fn.weight", PLAIN, vec![hc_dim, hc_mix]),
        ("hc_attn_scale.weight", &[F32][..], vec![3]),
        ("hc_attn_base.weight", &[F32][..], vec![hc_mix]),
        ("attn_norm.weight", &[F32][..], vec![shape.embd]),
        (
            "attn_q_a.weight",
            &[Q8_0][..],
            vec![shape.embd, shape.lora_q],
        ),
        ("attn_q_a_norm.weight", &[F32][..], vec![shape.lora_q]),
        ("attn_q_b.weight", &[Q8_0][..], vec![shape.lora_q, q_dim]),
        (
            "attn_kv.weight",
            &[Q8_0][..],
            vec![shape.embd, shape.head_dim],
        ),
        ("attn_kv_a_norm.weight", &[F32][..], vec![shape.head_dim]),
        ("attn_sinks.weight", &[F32][..], vec![shape.heads]),
        (
            "attn_output_a.weight",
            &[Q8_0][..],
            vec![
                shape.head_dim * (shape.heads / shape.out_groups),
                output_low,
            ],
        ),
        (
            "attn_output_b.weight",
            &[Q8_0][..],
            vec![output_low, shape.embd],
        ),
        ("hc_ffn_fn.weight", PLAIN, vec![hc_dim, hc_mix]),
        ("hc_ffn_scale.weight", &[F32][..], vec![3]),
        ("hc_ffn_base.weight", &[F32][..], vec![hc_mix]),
        ("ffn_norm.weight", &[F32][..], vec![shape.embd]),
        (
            "ffn_gate_inp.weight",
            PLAIN,
            vec![shape.embd, shape.experts],
        ),
        ("exp_probs_b.bias", &[F32][..], vec![shape.experts]),
        (
            "ffn_gate_exps.weight",
            ROUTED,
            vec![shape.embd, shape.ff_expert, shape.experts],
        ),
        (
            "ffn_up_exps.weight",
            ROUTED,
            vec![shape.embd, shape.ff_expert, shape.experts],
        ),
        (
            "ffn_down_exps.weight",
            ROUTED,
            vec![shape.ff_expert, shape.embd, shape.experts],
        ),
        (
            "ffn_gate_shexp.weight",
            &[Q8_0][..],
            vec![shape.embd, shape.ff_expert],
        ),
        (
            "ffn_up_shexp.weight",
            &[Q8_0][..],
            vec![shape.embd, shape.ff_expert],
        ),
        (
            "ffn_down_shexp.weight",
            &[Q8_0][..],
            vec![shape.ff_expert, shape.embd],
        ),
    ] {
        expect(model, &format!("{prefix}.{suffix}"), types, &dims)?;
    }
    same_type(
        model,
        "mtp.0.ffn_gate_exps.weight",
        "mtp.0.ffn_up_exps.weight",
    )
}

pub(super) fn validate_main(model: &Gguf, expected: ModelChoice) -> Result<Shape, String> {
    let family = if model.bytes("general.architecture").ok() == Some(b"glm-dsa") {
        ModelFamily::Glm
    } else {
        ModelFamily::DeepSeek
    };
    let shape = match family {
        ModelFamily::Glm => GLM,
        ModelFamily::DeepSeek => match (model.u32("deepseek4.block_count")?, expected) {
            (43, ModelChoice::DeepSeekV4Flash0731) => FLASH_0731,
            (43, _) => FLASH,
            (61, _) => PRO,
            (layers, _) => return Err(format!("unsupported DeepSeek layer count: {layers}")),
        },
    };
    if shape.model != expected {
        return Err(format!(
            "{} contains {}, but the selected model is {expected}",
            model.path().display(),
            shape.model
        ));
    }
    validate_metadata(model, &shape)?;
    validate_tensors(model, &shape)?;
    Ok(shape)
}

fn validate_metadata(model: &Gguf, shape: &Shape) -> Result<(), String> {
    let prefix = if shape.family == ModelFamily::Glm {
        "glm-dsa"
    } else {
        "deepseek4"
    };
    for (key, expected) in [
        ("block_count", u64::from(shape.layers)),
        ("embedding_length", shape.embd),
        ("vocab_size", shape.vocab),
        ("attention.head_count", shape.heads),
        ("attention.head_count_kv", shape.head_kv),
        ("attention.key_length", shape.head_dim),
        ("attention.value_length", shape.value_dim),
        ("rope.dimension_count", shape.rot),
        ("attention.q_lora_rank", shape.lora_q),
        ("expert_count", shape.experts),
        ("expert_used_count", shape.experts_used),
        ("expert_feed_forward_length", shape.ff_expert),
        ("expert_shared_count", shape.expert_shared),
        ("attention.indexer.head_count", shape.indexer_heads),
        ("attention.indexer.key_length", shape.indexer_head_dim),
        ("attention.indexer.top_k", shape.indexer_top_k),
    ] {
        expect_u64(model, &format!("{prefix}.{key}"), expected)?;
    }
    expect_float(
        model,
        &format!("{prefix}.attention.layer_norm_rms_epsilon"),
        shape.rms_epsilon,
    )?;
    expect_float(
        model,
        &format!("{prefix}.expert_weights_scale"),
        shape.expert_weight_scale,
    )?;
    if !model.boolean(&format!("{prefix}.expert_weights_norm"))? {
        return Err(format!("{prefix}.expert_weights_norm must be true"));
    }
    expect_float(model, &format!("{prefix}.rope.freq_base"), shape.rope_base)?;

    if shape.family == ModelFamily::Glm {
        for (key, expected) in [
            ("context_length", shape.original_context),
            ("feed_forward_length", shape.ff_dense),
            ("attention.kv_lora_rank", shape.kv_lora),
            ("attention.key_length_mla", shape.key_mla),
            ("attention.value_length_mla", shape.value_mla),
            ("expert_group_count", 1),
            ("expert_group_used_count", 1),
            ("expert_gating_func", 2),
            ("leading_dense_block_count", u64::from(shape.leading_dense)),
            ("nextn_predict_layers", u64::from(shape.nextn)),
        ] {
            expect_u64(model, &format!("{prefix}.{key}"), expected)?;
        }
        return Ok(());
    }

    for (key, expected) in [
        ("attention.output_group_count", shape.out_groups),
        ("attention.output_lora_rank", shape.lora_o),
        ("hash_layer_count", u64::from(shape.hash_layers)),
        ("attention.sliding_window", shape.sliding_window),
        ("hyper_connection.count", shape.hc),
        ("hyper_connection.sinkhorn_iterations", shape.hc_sinkhorn),
    ] {
        expect_u64(model, &format!("{prefix}.{key}"), expected)?;
    }
    for key in ["expert_group_count", "expert_group_used_count"] {
        if let Some(Value::U32(value)) = model.metadata.get(&format!("{prefix}.{key}"))
            && *value != 0
        {
            return Err(format!("{prefix}.{key} must be zero"));
        }
    }
    for (key, expected) in [
        ("hyper_connection.epsilon", shape.hc_epsilon),
        (
            "attention.compress_rope_freq_base",
            shape.compress_rope_base,
        ),
    ] {
        expect_float(model, &format!("{prefix}.{key}"), expected)?;
    }
    for (key, expected) in [
        ("rope.scaling.factor", shape.rope_scale),
        ("rope.scaling.yarn_beta_fast", shape.rope_beta_fast),
        ("rope.scaling.yarn_beta_slow", shape.rope_beta_slow),
    ] {
        if model.metadata.contains_key(&format!("{prefix}.{key}")) {
            expect_float(model, &format!("{prefix}.{key}"), expected)?;
        }
    }
    if model
        .metadata
        .contains_key("deepseek4.rope.scaling.original_context_length")
    {
        expect_u64(
            model,
            "deepseek4.rope.scaling.original_context_length",
            shape.original_context,
        )?;
    }
    let ratios = model.u32s("deepseek4.attention.compress_ratios")?;
    let clamps = model.f32s("deepseek4.swiglu_clamp_exp")?;
    if ratios.len() < shape.layers as usize || clamps.len() < shape.layers as usize {
        return Err("DeepSeek per-layer metadata is shorter than the layer count".into());
    }
    for layer in 0..shape.layers as usize {
        let expected = compression_ratio(shape, layer as u32);
        if ratios[layer] != expected {
            return Err(format!(
                "layer {layer} compression ratio is {}, expected {expected}",
                ratios[layer]
            ));
        }
        if !float_eq(clamps[layer], shape.swiglu_clamp) {
            return Err(format!("layer {layer} has an invalid SwiGLU clamp"));
        }
    }
    Ok(())
}

fn validate_tensors(model: &Gguf, shape: &Shape) -> Result<(), String> {
    match shape.family {
        ModelFamily::DeepSeek => validate_deepseek_tensors(model, shape),
        ModelFamily::Glm => validate_glm_tensors(model, shape),
    }
}

fn validate_deepseek_tensors(model: &Gguf, shape: &Shape) -> Result<(), String> {
    let hc_dim = shape.embd * shape.hc;
    let hc_mix = 2 * shape.hc + shape.hc * shape.hc;
    let q_dim = shape.heads * shape.head_dim;
    let output_low = shape.out_groups * shape.lora_o;
    expect(
        model,
        "token_embd.weight",
        &[F16],
        &[shape.embd, shape.vocab],
    )?;
    expect(model, "output_hc_base.weight", &[F32], &[shape.hc])?;
    expect(model, "output_hc_fn.weight", &[F16], &[hc_dim, shape.hc])?;
    expect(model, "output_hc_scale.weight", &[F32], &[1])?;
    expect(model, "output_norm.weight", &[F32], &[shape.embd])?;
    expect(model, "output.weight", DENSE, &[shape.embd, shape.vocab])?;

    for layer in 0..shape.layers {
        let name = |suffix: &str| format!("blk.{layer}.{suffix}");
        expect(model, &name("hc_attn_fn.weight"), &[F16], &[hc_dim, hc_mix])?;
        expect(model, &name("hc_attn_scale.weight"), &[F32], &[3])?;
        expect(model, &name("hc_attn_base.weight"), &[F32], &[hc_mix])?;
        expect(model, &name("attn_norm.weight"), &[F32], &[shape.embd])?;
        expect(
            model,
            &name("attn_q_a.weight"),
            DENSE,
            &[shape.embd, shape.lora_q],
        )?;
        expect(
            model,
            &name("attn_q_a_norm.weight"),
            &[F32],
            &[shape.lora_q],
        )?;
        expect(
            model,
            &name("attn_q_b.weight"),
            DENSE,
            &[shape.lora_q, q_dim],
        )?;
        expect(
            model,
            &name("attn_kv.weight"),
            DENSE,
            &[shape.embd, shape.head_dim],
        )?;
        expect(
            model,
            &name("attn_kv_a_norm.weight"),
            &[F32],
            &[shape.head_dim],
        )?;
        expect(model, &name("attn_sinks.weight"), &[F32], &[shape.heads])?;
        expect(
            model,
            &name("attn_output_a.weight"),
            DENSE,
            &[
                shape.head_dim * (shape.heads / shape.out_groups),
                output_low,
            ],
        )?;
        expect(
            model,
            &name("attn_output_b.weight"),
            DENSE,
            &[output_low, shape.embd],
        )?;

        let ratio = compression_ratio(shape, layer);
        if ratio != 0 {
            let compression_width = if ratio == 4 { 2 } else { 1 } * shape.head_dim;
            expect(
                model,
                &name("attn_compressor_ape.weight"),
                &[F16],
                &[compression_width, u64::from(ratio)],
            )?;
            expect(
                model,
                &name("attn_compressor_kv.weight"),
                &[F16],
                &[shape.embd, compression_width],
            )?;
            expect(
                model,
                &name("attn_compressor_gate.weight"),
                &[F16],
                &[shape.embd, compression_width],
            )?;
            expect(
                model,
                &name("attn_compressor_norm.weight"),
                &[F32],
                &[shape.head_dim],
            )?;
        }
        if ratio == 4 {
            let index_q = shape.indexer_heads * shape.indexer_head_dim;
            let index_width = 2 * shape.indexer_head_dim;
            expect(
                model,
                &name("indexer.attn_q_b.weight"),
                &[F16, Q8_0],
                &[shape.lora_q, index_q],
            )?;
            expect(
                model,
                &name("indexer.proj.weight"),
                &[F16],
                &[shape.embd, shape.indexer_heads],
            )?;
            expect(
                model,
                &name("indexer_compressor_ape.weight"),
                &[F16],
                &[index_width, 4],
            )?;
            expect(
                model,
                &name("indexer_compressor_kv.weight"),
                &[F16],
                &[shape.embd, index_width],
            )?;
            expect(
                model,
                &name("indexer_compressor_gate.weight"),
                &[F16],
                &[shape.embd, index_width],
            )?;
            expect(
                model,
                &name("indexer_compressor_norm.weight"),
                &[F32],
                &[shape.indexer_head_dim],
            )?;
        }
        expect(model, &name("hc_ffn_fn.weight"), &[F16], &[hc_dim, hc_mix])?;
        expect(model, &name("hc_ffn_scale.weight"), &[F32], &[3])?;
        expect(model, &name("hc_ffn_base.weight"), &[F32], &[hc_mix])?;
        expect(model, &name("ffn_norm.weight"), &[F32], &[shape.embd])?;
        expect(
            model,
            &name("ffn_gate_inp.weight"),
            &[F16],
            &[shape.embd, shape.experts],
        )?;
        expect_optional(model, &name("exp_probs_b.bias"), &[F32], &[shape.experts])?;
        expect(
            model,
            &name("ffn_gate_exps.weight"),
            ROUTED,
            &[shape.embd, shape.ff_expert, shape.experts],
        )?;
        expect(
            model,
            &name("ffn_up_exps.weight"),
            ROUTED,
            &[shape.embd, shape.ff_expert, shape.experts],
        )?;
        expect(
            model,
            &name("ffn_down_exps.weight"),
            ROUTED,
            &[shape.ff_expert, shape.embd, shape.experts],
        )?;
        same_type(
            model,
            &name("ffn_gate_exps.weight"),
            &name("ffn_up_exps.weight"),
        )?;
        expect(
            model,
            &name("ffn_gate_shexp.weight"),
            DENSE,
            &[shape.embd, shape.ff_expert],
        )?;
        expect(
            model,
            &name("ffn_up_shexp.weight"),
            DENSE,
            &[shape.embd, shape.ff_expert],
        )?;
        expect(
            model,
            &name("ffn_down_shexp.weight"),
            DENSE,
            &[shape.ff_expert, shape.embd],
        )?;
        if layer < shape.hash_layers {
            expect(
                model,
                &name("ffn_gate_tid2eid.weight"),
                &[I32],
                &[shape.experts_used, shape.vocab],
            )?;
        }
    }
    Ok(())
}

fn validate_glm_tensors(model: &Gguf, shape: &Shape) -> Result<(), String> {
    let q_dim = shape.heads * shape.key_mla;
    let q_nope = shape.key_mla - shape.rot;
    let index_q = shape.indexer_heads * shape.indexer_head_dim;
    expect(
        model,
        "token_embd.weight",
        DENSE,
        &[shape.embd, shape.vocab],
    )?;
    expect(model, "output_norm.weight", &[F32], &[shape.embd])?;
    expect(model, "output.weight", DENSE, &[shape.embd, shape.vocab])?;
    for layer in 0..shape.layers {
        let name = |suffix: &str| format!("blk.{layer}.{suffix}");
        expect(model, &name("attn_norm.weight"), &[F32], &[shape.embd])?;
        expect(
            model,
            &name("attn_q_a.weight"),
            DENSE,
            &[shape.embd, shape.lora_q],
        )?;
        expect(
            model,
            &name("attn_q_a_norm.weight"),
            &[F32],
            &[shape.lora_q],
        )?;
        expect(
            model,
            &name("attn_q_b.weight"),
            DENSE,
            &[shape.lora_q, q_dim],
        )?;
        expect(
            model,
            &name("attn_kv_a_mqa.weight"),
            DENSE,
            &[shape.embd, shape.head_dim],
        )?;
        expect(
            model,
            &name("attn_kv_a_norm.weight"),
            &[F32],
            &[shape.kv_lora],
        )?;
        expect(
            model,
            &name("attn_k_b.weight"),
            DENSE,
            &[q_nope, shape.kv_lora, shape.heads],
        )?;
        expect(
            model,
            &name("attn_v_b.weight"),
            DENSE,
            &[shape.kv_lora, shape.value_mla, shape.heads],
        )?;
        expect(
            model,
            &name("attn_output.weight"),
            DENSE,
            &[shape.heads * shape.value_mla, shape.embd],
        )?;
        expect(
            model,
            &name("indexer.attn_k.weight"),
            DENSE,
            &[shape.embd, shape.indexer_head_dim],
        )?;
        expect(
            model,
            &name("indexer.attn_q_b.weight"),
            DENSE,
            &[shape.lora_q, index_q],
        )?;
        expect(
            model,
            &name("indexer.k_norm.weight"),
            &[F32],
            &[shape.indexer_head_dim],
        )?;
        expect(
            model,
            &name("indexer.k_norm.bias"),
            &[F32],
            &[shape.indexer_head_dim],
        )?;
        expect(
            model,
            &name("indexer.proj.weight"),
            &[F32],
            &[shape.embd, shape.indexer_heads],
        )?;
        expect(model, &name("ffn_norm.weight"), &[F32], &[shape.embd])?;
        if layer < shape.leading_dense {
            expect(
                model,
                &name("ffn_gate.weight"),
                DENSE,
                &[shape.embd, shape.ff_dense],
            )?;
            expect(
                model,
                &name("ffn_up.weight"),
                DENSE,
                &[shape.embd, shape.ff_dense],
            )?;
            expect(
                model,
                &name("ffn_down.weight"),
                DENSE,
                &[shape.ff_dense, shape.embd],
            )?;
        } else {
            expect(
                model,
                &name("ffn_gate_inp.weight"),
                &[F32],
                &[shape.embd, shape.experts],
            )?;
            expect(model, &name("exp_probs_b.bias"), &[F32], &[shape.experts])?;
            expect(
                model,
                &name("ffn_gate_exps.weight"),
                ROUTED,
                &[shape.embd, shape.ff_expert, shape.experts],
            )?;
            expect(
                model,
                &name("ffn_up_exps.weight"),
                ROUTED,
                &[shape.embd, shape.ff_expert, shape.experts],
            )?;
            expect(
                model,
                &name("ffn_down_exps.weight"),
                ROUTED,
                &[shape.ff_expert, shape.embd, shape.experts],
            )?;
            same_type(
                model,
                &name("ffn_gate_exps.weight"),
                &name("ffn_up_exps.weight"),
            )?;
            expect(
                model,
                &name("ffn_gate_shexp.weight"),
                DENSE,
                &[shape.embd, shape.ff_expert],
            )?;
            expect(
                model,
                &name("ffn_up_shexp.weight"),
                DENSE,
                &[shape.embd, shape.ff_expert],
            )?;
            expect(
                model,
                &name("ffn_down_shexp.weight"),
                DENSE,
                &[shape.ff_expert, shape.embd],
            )?;
        }
        if layer + shape.nextn >= shape.layers {
            expect(
                model,
                &name("nextn.eh_proj.weight"),
                DENSE,
                &[2 * shape.embd, shape.embd],
            )?;
            expect(model, &name("nextn.enorm.weight"), &[F32], &[shape.embd])?;
            expect(model, &name("nextn.hnorm.weight"), &[F32], &[shape.embd])?;
            expect(
                model,
                &name("nextn.shared_head_norm.weight"),
                &[F32],
                &[shape.embd],
            )?;
        }
    }
    Ok(())
}

pub(super) fn validate_dspark(model: &Gguf, shape: &Shape) -> Result<(), String> {
    if !matches!(
        shape.model,
        ModelChoice::DeepSeekV4Flash | ModelChoice::DeepSeekV4Flash0731
    ) {
        return Err("DSpark support is available only for DeepSeek V4 Flash".into());
    }
    let DsparkConfig {
        block_size,
        markov_rank,
        noise_token,
        target_layers: targets,
        stages,
    } = dspark_config(model)?;
    if !(1..=16).contains(&block_size) || markov_rank == 0 || noise_token >= shape.vocab as u32 {
        return Err("invalid DSpark block, Markov, or noise-token metadata".into());
    }
    if targets.is_empty()
        || targets.len() > 8
        || targets.windows(2).any(|pair| pair[0] >= pair[1])
        || targets.iter().any(|layer| *layer >= shape.layers)
    {
        return Err("invalid DSpark target-layer metadata".into());
    }
    if !(1..=8).contains(&stages) {
        return Err(format!("invalid DSpark stage count: {stages}"));
    }
    for stage in 0..stages {
        validate_dspark_block(model, shape, stage)?;
        if stage == 0 {
            expect(
                model,
                &format!("mtp.{stage}.main_proj.weight"),
                DSPARK_DENSE,
                &[targets.len() as u64 * shape.embd, shape.embd],
            )?;
            expect(
                model,
                &format!("mtp.{stage}.main_norm.weight"),
                &[F32],
                &[shape.embd],
            )?;
        }
    }
    let prefix = format!("mtp.{}", stages - 1);
    expect(
        model,
        &format!("{prefix}.norm.weight"),
        &[F32],
        &[shape.embd],
    )?;
    expect(
        model,
        &format!("{prefix}.hc_head_base.weight"),
        &[F32],
        &[shape.hc],
    )?;
    expect(
        model,
        &format!("{prefix}.hc_head_fn.weight"),
        PLAIN,
        &[shape.embd * shape.hc, shape.hc],
    )?;
    expect(
        model,
        &format!("{prefix}.hc_head_scale.weight"),
        &[F32],
        &[1],
    )?;
    expect(
        model,
        &format!("{prefix}.markov_head.markov_w1.weight"),
        DSPARK_DENSE,
        &[u64::from(markov_rank), shape.vocab],
    )?;
    expect(
        model,
        &format!("{prefix}.markov_head.markov_w2.weight"),
        DSPARK_DENSE,
        &[u64::from(markov_rank), shape.vocab],
    )?;
    expect(
        model,
        &format!("{prefix}.confidence_head.proj.weight"),
        DSPARK_DENSE,
        &[shape.embd + u64::from(markov_rank), 1],
    )?;
    Ok(())
}

fn validate_dspark_block(model: &Gguf, shape: &Shape, stage: u32) -> Result<(), String> {
    let hc_dim = shape.embd * shape.hc;
    let hc_mix = 2 * shape.hc + shape.hc * shape.hc;
    let q_dim = shape.heads * shape.head_dim;
    let output_low = shape.out_groups * shape.lora_o;
    let name = |suffix: &str| format!("mtp.{stage}.{suffix}");
    for (suffix, types, dims) in [
        ("hc_attn_fn.weight", PLAIN, vec![hc_dim, hc_mix]),
        ("hc_attn_scale.weight", &[F32][..], vec![3]),
        ("hc_attn_base.weight", &[F32][..], vec![hc_mix]),
        ("attn_norm.weight", &[F32][..], vec![shape.embd]),
        (
            "attn_q_a.weight",
            DSPARK_DENSE,
            vec![shape.embd, shape.lora_q],
        ),
        ("attn_q_a_norm.weight", &[F32][..], vec![shape.lora_q]),
        ("attn_q_b.weight", DSPARK_DENSE, vec![shape.lora_q, q_dim]),
        (
            "attn_kv.weight",
            DSPARK_DENSE,
            vec![shape.embd, shape.head_dim],
        ),
        ("attn_kv_a_norm.weight", &[F32][..], vec![shape.head_dim]),
        ("attn_sinks.weight", &[F32][..], vec![shape.heads]),
        (
            "attn_output_a.weight",
            DSPARK_DENSE,
            vec![
                shape.head_dim * (shape.heads / shape.out_groups),
                output_low,
            ],
        ),
        (
            "attn_output_b.weight",
            DSPARK_DENSE,
            vec![output_low, shape.embd],
        ),
        ("hc_ffn_fn.weight", PLAIN, vec![hc_dim, hc_mix]),
        ("hc_ffn_scale.weight", &[F32][..], vec![3]),
        ("hc_ffn_base.weight", &[F32][..], vec![hc_mix]),
        ("ffn_norm.weight", &[F32][..], vec![shape.embd]),
        (
            "ffn_gate_inp.weight",
            DSPARK_DENSE,
            vec![shape.embd, shape.experts],
        ),
        ("exp_probs_b.bias", &[F32][..], vec![shape.experts]),
        (
            "ffn_gate_exps.weight",
            ROUTED,
            vec![shape.embd, shape.ff_expert, shape.experts],
        ),
        (
            "ffn_up_exps.weight",
            ROUTED,
            vec![shape.embd, shape.ff_expert, shape.experts],
        ),
        (
            "ffn_down_exps.weight",
            ROUTED,
            vec![shape.ff_expert, shape.embd, shape.experts],
        ),
        (
            "ffn_gate_shexp.weight",
            DSPARK_DENSE,
            vec![shape.embd, shape.ff_expert],
        ),
        (
            "ffn_up_shexp.weight",
            DSPARK_DENSE,
            vec![shape.embd, shape.ff_expert],
        ),
        (
            "ffn_down_shexp.weight",
            DSPARK_DENSE,
            vec![shape.ff_expert, shape.embd],
        ),
    ] {
        expect(model, &name(suffix), types, &dims)?;
    }
    same_type(
        model,
        &name("ffn_gate_exps.weight"),
        &name("ffn_up_exps.weight"),
    )
}

fn expect(model: &Gguf, name: &str, types: &[u32], dims: &[u64]) -> Result<(), String> {
    validate_tensor(name, model.tensor(name)?, types, dims)
}

fn expect_optional(model: &Gguf, name: &str, types: &[u32], dims: &[u64]) -> Result<(), String> {
    match model.tensors.get(name) {
        Some(tensor) => validate_tensor(name, tensor, types, dims),
        None => Ok(()),
    }
}

fn validate_tensor(name: &str, tensor: &Tensor, types: &[u32], dims: &[u64]) -> Result<(), String> {
    if !types.contains(&tensor.kind) {
        return Err(format!(
            "tensor {name} has unsupported type {}",
            tensor.kind
        ));
    }
    if tensor.dims != dims {
        return Err(format!(
            "tensor {name} has dimensions {:?}, expected {dims:?}",
            tensor.dims
        ));
    }
    Ok(())
}

fn same_type(model: &Gguf, first: &str, second: &str) -> Result<(), String> {
    if model.tensor(first)?.kind != model.tensor(second)?.kind {
        Err(format!(
            "tensors {first} and {second} use different quantizations"
        ))
    } else {
        Ok(())
    }
}

fn expect_u64(model: &Gguf, key: &str, expected: u64) -> Result<(), String> {
    let actual = model.u64(key)?;
    if actual == expected {
        Ok(())
    } else {
        Err(format!("{key} is {actual}, expected {expected}"))
    }
}

fn expect_float(model: &Gguf, key: &str, expected: f32) -> Result<(), String> {
    let actual = model.f32(key)?;
    if float_eq(actual, expected) {
        Ok(())
    } else {
        Err(format!("{key} is {actual}, expected {expected}"))
    }
}

fn float_eq(actual: f32, expected: f32) -> bool {
    actual.is_finite() && (actual - expected).abs() <= expected.abs().max(1.0) * 1.0e-6
}

fn compression_ratio(shape: &Shape, layer: u32) -> u32 {
    match shape.model {
        ModelChoice::DeepSeekV4Flash | ModelChoice::DeepSeekV4Flash0731 if layer < 2 => 0,
        ModelChoice::DeepSeekV4Pro if layer < 2 => 128,
        ModelChoice::DeepSeekV4Flash
        | ModelChoice::DeepSeekV4Flash0731
        | ModelChoice::DeepSeekV4Pro
            if layer.is_multiple_of(2) =>
        {
            4
        }
        ModelChoice::DeepSeekV4Flash
        | ModelChoice::DeepSeekV4Flash0731
        | ModelChoice::DeepSeekV4Pro => 128,
        ModelChoice::Glm52 => 0,
    }
}

fn first_u32(model: &Gguf, keys: &[&str]) -> Result<u32, String> {
    keys.iter()
        .find_map(|key| model.u32(key).ok())
        .ok_or_else(|| format!("required DSpark metadata is missing: {}", keys[0]))
}

fn first_u32s<'a>(model: &'a Gguf, keys: &[&str]) -> Result<&'a [u32], String> {
    keys.iter()
        .find_map(|key| model.u32s(key).ok())
        .ok_or_else(|| format!("required DSpark metadata is missing: {}", keys[0]))
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn installed_ds4_fixture_opens_and_renders_a_prompt() {
        let path = crate::model::engine_artifacts(
            ModelChoice::DeepSeekV4Flash,
            false,
            false,
            &crate::app::models_path(),
        )
        .model;
        if !path.exists() {
            return;
        }
        let model = Model::open_main(&path, ModelChoice::DeepSeekV4Flash).unwrap();
        let summary = model.summary();
        assert_eq!(summary.model, ModelChoice::DeepSeekV4Flash);
        assert_eq!(summary.vocabulary_size, 129_280);
        assert_eq!(
            model.tokenize("Hello, world! 1234\nint café = 7;\n中文テスト"),
            [
                19_923, 14, 2_058, 3, 223, 6_895, 22, 201, 650, 57_664, 438, 223, 25, 510, 21_134,
                109_288,
            ]
        );
        assert_eq!(
            model.render_prompt("", "Hello", ReasoningMode::Direct),
            [0, 128_803, 19_923, 128_804, 128_822]
        );
        assert_eq!(model.tokenizer.tokenize_rendered("｜DSML｜").len(), 1);
        assert!(model.is_stop_token_for_reasoning(128_822, ReasoningMode::Direct));
        assert!(!model.is_stop_token_for_reasoning(128_822, ReasoningMode::High));
        let think_start = *model
            .render_prompt("", "Hello", ReasoningMode::High)
            .last()
            .unwrap();
        assert_eq!(
            model.render_conversation(
                "",
                &[
                    ChatTurn {
                        user: true,
                        tool: false,
                        system: false,
                        skip_previous_eos: false,
                        reasoning: None,
                        reasoning_complete: true,
                        content: "Hello".into(),
                    },
                    ChatTurn {
                        user: false,
                        tool: false,
                        system: false,
                        skip_previous_eos: false,
                        reasoning: None,
                        reasoning_complete: true,
                        content: "Hello".into(),
                    },
                    ChatTurn {
                        user: true,
                        tool: false,
                        system: false,
                        skip_previous_eos: false,
                        reasoning: None,
                        reasoning_complete: true,
                        content: "Hello".into(),
                    },
                ],
                ReasoningMode::Direct,
            ),
            [
                0, 128_803, 19_923, 128_804, 128_822, 19_923, 1, 128_803, 19_923, 128_804, 128_822,
            ]
        );
        assert_eq!(
            model.render_continuation("Hello", ReasoningMode::Direct, false),
            [1, 128_803, 19_923, 128_804, 128_822]
        );
        assert_eq!(
            model.render_continuation("Hello", ReasoningMode::Direct, true),
            [128_803, 19_923, 128_804, 128_822]
        );
        assert_eq!(
            model.render_conversation(
                "",
                &[
                    ChatTurn {
                        user: false,
                        tool: false,
                        system: true,
                        skip_previous_eos: false,
                        reasoning: None,
                        reasoning_complete: true,
                        content: "Hello".into(),
                    },
                    ChatTurn {
                        user: true,
                        tool: false,
                        system: false,
                        skip_previous_eos: false,
                        reasoning: None,
                        reasoning_complete: true,
                        content: "Hello".into(),
                    },
                ],
                ReasoningMode::Direct,
            ),
            [0, 19_923, 128_803, 19_923, 128_804, 128_822]
        );
        assert_eq!(
            model.render_history(
                "",
                &[
                    ChatTurn {
                        user: true,
                        tool: false,
                        system: false,
                        skip_previous_eos: false,
                        reasoning: None,
                        reasoning_complete: true,
                        content: "Hello".into(),
                    },
                    ChatTurn {
                        user: false,
                        tool: false,
                        system: false,
                        skip_previous_eos: false,
                        reasoning: None,
                        reasoning_complete: true,
                        content: "Hello".into(),
                    },
                ],
                ReasoningMode::Direct,
            ),
            [0, 128_803, 19_923, 128_804, 128_822, 19_923]
        );
        let tool_turn = ChatTurn {
            user: false,
            tool: true,
            system: false,
            skip_previous_eos: false,
            reasoning: None,
            reasoning_complete: true,
            content: "Hello".into(),
        };
        let wrapped_user = ChatTurn {
            user: true,
            tool: false,
            system: false,
            skip_previous_eos: false,
            reasoning: None,
            reasoning_complete: true,
            content: "<tool_result>Hello</tool_result>".into(),
        };
        assert_eq!(
            model.render_conversation("", &[tool_turn], ReasoningMode::Direct),
            model.render_conversation("", &[wrapped_user], ReasoningMode::Direct)
        );
        assert_eq!(
            model.render_conversation(
                "",
                &[
                    ChatTurn {
                        user: true,
                        tool: false,
                        system: false,
                        skip_previous_eos: false,
                        reasoning: None,
                        reasoning_complete: true,
                        content: "Hello".into(),
                    },
                    ChatTurn {
                        user: false,
                        tool: false,
                        system: false,
                        skip_previous_eos: false,
                        reasoning: Some("Hello".into()),
                        reasoning_complete: true,
                        content: "Hello".into(),
                    },
                    ChatTurn {
                        user: true,
                        tool: false,
                        system: false,
                        skip_previous_eos: false,
                        reasoning: None,
                        reasoning_complete: true,
                        content: "Hello".into(),
                    },
                ],
                ReasoningMode::Direct,
            ),
            [
                0,
                128_803,
                19_923,
                128_804,
                think_start,
                19_923,
                128_822,
                19_923,
                1,
                128_803,
                19_923,
                128_804,
                128_822,
            ]
        );
    }

    #[test]
    fn installed_dspark_fixture_passes_the_target_layout() {
        let path = crate::model::engine_artifacts(
            ModelChoice::DeepSeekV4Flash,
            false,
            true,
            &crate::app::models_path(),
        )
        .mtp
        .unwrap();
        if path.exists() {
            validate_model_artifact(&path, ModelChoice::DeepSeekV4Flash, true).unwrap();
        }
    }

    #[test]
    fn installed_legacy_mtp_fixture_passes_the_target_layout() {
        let path = crate::model::engine_artifacts(
            ModelChoice::DeepSeekV4Flash,
            true,
            false,
            &crate::app::models_path(),
        )
        .mtp
        .unwrap();
        if path.exists() {
            assert_eq!(
                validate_support(&Gguf::open(&path).unwrap(), &FLASH).unwrap(),
                SupportKind::LegacyMtp
            );
        }
    }
}
