//! M4 — verify the `#[view_plugin(...)]` proc-macro shares the
//! linkme-slice walker with `#[plugin]` and `#[capability_plugin]`,
//! so a view plugin whose crate contributes an entity registration
//! reports it in the manifest's `declared_types`.
//!
//! Pre-M4 the `#[view_plugin]` macro hardcoded
//! `declared_types: Vec::new()` (and similarly for handlers /
//! capabilities / phases / wire_frames). Wire-frame compatibility
//! checking, theoretical today, could never be enforced for view
//! plugins. This test pins the post-M4 behaviour: the walker fires,
//! and a sibling `#[derive(EntityType)]` in the same crate flows
//! through to the view manifest.

use maat::traits::ViewPluginMetadata;
use maat_sdk::plugin::PluginKind;
use maat_sdk::traits::FeaturedData;
use maat_sdk_derive::{view_plugin, EntityType};

// M4 — co-located entity. The view plugin lives in this crate, so
// the linkme-slice walker emitted by `#[view_plugin]` should pick
// this entity up and report it in `manifest.declared_types`.
#[derive(EntityType)]
#[entity(type_id = 9201, display = "View Render Decal")]
#[allow(dead_code)]
pub struct ViewRenderDecal {
    pub featured: FeaturedData,
}

#[derive(Debug, Default)]
#[view_plugin(
    canonical_id = "github.com/maat/test-dummy-view",
    display_name = "Test Dummy View",
    authors      = ["Test Author"],
    description  = "Macro smoke-test view plugin",
    license      = "MIT",
)]
pub struct DummyView;

#[test]
fn view_manifest_has_expected_shape() {
    let meta = DummyViewMetadata;
    let manifest = ViewPluginMetadata::manifest(&meta);
    assert_eq!(manifest.canonical_id.as_str(), "github.com/maat/test-dummy-view");
    assert_eq!(manifest.display_name, "Test Dummy View");
    assert_eq!(manifest.kind, PluginKind::View);
    assert_eq!(manifest.license.as_str(), "MIT");
}

#[test]
fn view_manifest_walks_declared_types() {
    let meta = DummyViewMetadata;
    let manifest = ViewPluginMetadata::manifest(&meta);
    let names: Vec<&str> = manifest
        .declared_types
        .iter()
        .map(|t| t.type_name.as_str())
        .collect();
    assert!(
        names.contains(&"ViewRenderDecal"),
        "view manifest should report sibling entity in declared_types; got {names:?}"
    );
}

#[test]
fn view_manifest_decls_have_correct_shape() {
    // Even when no producer-side registration exists for a given slice,
    // the walker still emits an empty vec — proving the field is alive
    // (not hardcoded) and ready to populate once registration arrives.
    let meta = DummyViewMetadata;
    let manifest = ViewPluginMetadata::manifest(&meta);
    let _: &Vec<_> = &manifest.declared_wire_frames;
    let _: &Vec<_> = &manifest.declared_handlers;
    let _: &Vec<_> = &manifest.declared_capabilities;
    let _: &Vec<_> = &manifest.declared_phases;
}

// ---------------------------------------------------------------------------
// M2 — `#[view_plugin(dependencies = [...])]` populates
// `PluginManifest::dependencies`.  Mirrors the model- and capability-
// plugin M2 tests.
// ---------------------------------------------------------------------------

#[derive(Debug, Default)]
#[view_plugin(
    canonical_id = "github.com/maat/test-view-with-deps",
    license      = "MIT",
    dependencies = ["github.com/maat/checkers"],
)]
pub struct DepView;

#[test]
fn view_plugin_with_dependencies_populates_manifest() {
    let meta = DepViewMetadata;
    let m = ViewPluginMetadata::manifest(&meta);
    assert_eq!(m.dependencies.len(), 1);
    assert_eq!(m.dependencies[0].canonical_id.as_str(), "github.com/maat/checkers");
    assert!(m.dependencies[0].required);
}

#[test]
fn view_plugin_without_dependencies_is_empty() {
    let meta = DummyViewMetadata;
    let m = ViewPluginMetadata::manifest(&meta);
    assert!(m.dependencies.is_empty());
}
