use crate::common::{create_config, fixture_path};

#[test]
fn lit_custom_element_class_exports_credited_through_decorator_and_define() {
    let root = fixture_path("lit-custom-element");
    let config = create_config(root);
    let results = fallow_core::analyze(&config).expect("analysis should succeed");

    let unused_export_names: Vec<&str> = results
        .unused_exports
        .iter()
        .map(|e| e.export.export_name.as_str())
        .collect();

    assert!(
        !unused_export_names.contains(&"MyElement"),
        "Lit @customElement-decorated class should be credited as side-effect-used, found unused exports: {unused_export_names:?}"
    );
    assert!(
        !unused_export_names.contains(&"OtherElement"),
        "customElements.define-registered class should be credited as side-effect-used, found: {unused_export_names:?}"
    );
    assert!(
        !unused_export_names.contains(&"SeparateElement"),
        "class registered after its export statement should still be credited, found: {unused_export_names:?}"
    );
    assert!(
        !unused_export_names.contains(&"AliasedElement"),
        "namespace-aliased @customElement form should also be credited, found: {unused_export_names:?}"
    );
    assert!(
        !unused_export_names.contains(&"NamedImportAliasedElement"),
        "named-import-aliased @customElement form should also be credited, found: {unused_export_names:?}"
    );

    let anonymous_default_unused = results.unused_exports.iter().any(|e| {
        e.export.path.ends_with("anonymous-default.ts") && e.export.export_name == "default"
    });
    assert!(
        !anonymous_default_unused,
        "anonymous default-exported @customElement class should be credited, unused exports were: {:?}",
        results
            .unused_exports
            .iter()
            .map(|e| (
                e.export.path.to_string_lossy().into_owned(),
                e.export.export_name.clone()
            ))
            .collect::<Vec<_>>()
    );
}

#[test]
fn lit_lifecycle_methods_not_flagged_but_genuinely_unused_methods_are() {
    let root = fixture_path("lit-custom-element");
    let config = create_config(root);
    let results = fallow_core::analyze(&config).expect("analysis should succeed");

    let unused: Vec<String> = results
        .unused_class_members
        .iter()
        .map(|m| format!("{}.{}", m.member.parent_name, m.member.member_name))
        .collect();

    assert!(
        !unused.contains(&"MyElement.render".to_string()),
        "render() on LitElement subclass should be plugin-allowlisted, found: {unused:?}"
    );
    assert!(
        !unused.contains(&"MyElement.connectedCallback".to_string()),
        "connectedCallback on LitElement should be allowlisted, found: {unused:?}"
    );
    assert!(
        !unused.contains(&"OtherElement.connectedCallback".to_string()),
        "connectedCallback on HTMLElement subclass should be allowlisted, found: {unused:?}"
    );
    assert!(
        !unused.contains(&"OtherElement.observedAttributes".to_string()),
        "observedAttributes on HTMLElement should be allowlisted, found: {unused:?}"
    );
    assert!(
        unused.contains(&"MyElement.unusedHelper".to_string()),
        "non-lifecycle unused method on a LitElement should still be reported, found: {unused:?}"
    );
    assert!(
        unused.contains(&"OtherElement.unusedNativeHelper".to_string()),
        "non-lifecycle unused method on an HTMLElement should still be reported, found: {unused:?}"
    );
}
