use eidos_kernel::schema::Kind;

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum FieldShape {
    Scalar,
    List,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ProfileNodeKind {
    Any,
    Doc,
    Skill,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct FieldProfile {
    pub name: &'static str,
    pub shape: FieldShape,
    pub required_for: &'static [ProfileNodeKind],
    pub recommended_for: &'static [ProfileNodeKind],
    pub legacy_replacement: Option<&'static str>,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct LegacyValueProfile {
    pub field: &'static str,
    pub value: &'static str,
    pub replacement: &'static str,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct AunFrontmatterProfile {
    pub fields: &'static [FieldProfile],
    pub valid_statuses: &'static [&'static str],
    pub valid_kinds: &'static [&'static str],
    pub legacy_kind_values: &'static [LegacyValueProfile],
}

const ANY: &[ProfileNodeKind] = &[ProfileNodeKind::Any];
const DOC_SKILL: &[ProfileNodeKind] = &[ProfileNodeKind::Doc, ProfileNodeKind::Skill];

const FIELDS: &[FieldProfile] = &[
    FieldProfile {
        name: "aliases",
        shape: FieldShape::List,
        required_for: &[],
        recommended_for: ANY,
        legacy_replacement: None,
    },
    FieldProfile {
        name: "consumes",
        shape: FieldShape::List,
        required_for: &[],
        recommended_for: &[],
        legacy_replacement: None,
    },
    FieldProfile {
        name: "contracts",
        shape: FieldShape::List,
        required_for: &[],
        recommended_for: &[],
        legacy_replacement: None,
    },
    FieldProfile {
        name: "depends_on",
        shape: FieldShape::List,
        required_for: &[],
        recommended_for: &[],
        legacy_replacement: None,
    },
    FieldProfile {
        name: "description",
        shape: FieldShape::Scalar,
        required_for: &[],
        recommended_for: DOC_SKILL,
        legacy_replacement: Some("summary"),
    },
    FieldProfile {
        name: "dispatches",
        shape: FieldShape::List,
        required_for: &[],
        recommended_for: &[],
        legacy_replacement: None,
    },
    FieldProfile {
        name: "keywords",
        shape: FieldShape::List,
        required_for: &[],
        recommended_for: ANY,
        legacy_replacement: Some("aliases"),
    },
    FieldProfile {
        name: "kind",
        shape: FieldShape::Scalar,
        required_for: &[],
        recommended_for: &[],
        legacy_replacement: Some("type"),
    },
    FieldProfile {
        name: "name",
        shape: FieldShape::Scalar,
        required_for: &[ProfileNodeKind::Skill],
        recommended_for: &[],
        legacy_replacement: Some("title"),
    },
    FieldProfile {
        name: "produces",
        shape: FieldShape::List,
        required_for: &[],
        recommended_for: &[],
        legacy_replacement: None,
    },
    FieldProfile {
        name: "query_examples",
        shape: FieldShape::List,
        required_for: &[],
        recommended_for: ANY,
        legacy_replacement: None,
    },
    FieldProfile {
        name: "asserts",
        shape: FieldShape::List,
        required_for: &[],
        recommended_for: &[],
        legacy_replacement: None,
    },
    FieldProfile {
        name: "qualifies",
        shape: FieldShape::List,
        required_for: &[],
        recommended_for: &[],
        legacy_replacement: None,
    },
    FieldProfile {
        name: "related",
        shape: FieldShape::List,
        required_for: &[],
        recommended_for: &[],
        legacy_replacement: None,
    },
    FieldProfile {
        name: "resource",
        shape: FieldShape::Scalar,
        required_for: &[],
        recommended_for: &[],
        legacy_replacement: None,
    },
    FieldProfile {
        name: "status",
        shape: FieldShape::Scalar,
        required_for: &[],
        recommended_for: ANY,
        legacy_replacement: None,
    },
    FieldProfile {
        name: "summary",
        shape: FieldShape::Scalar,
        required_for: &[],
        recommended_for: DOC_SKILL,
        legacy_replacement: None,
    },
    FieldProfile {
        name: "supports",
        shape: FieldShape::List,
        required_for: &[],
        recommended_for: &[],
        legacy_replacement: None,
    },
    FieldProfile {
        name: "tags",
        shape: FieldShape::List,
        required_for: &[],
        recommended_for: ANY,
        legacy_replacement: None,
    },
    FieldProfile {
        name: "timestamp",
        shape: FieldShape::Scalar,
        required_for: &[],
        recommended_for: &[],
        legacy_replacement: None,
    },
    FieldProfile {
        name: "title",
        shape: FieldShape::Scalar,
        required_for: &[ProfileNodeKind::Doc],
        recommended_for: &[],
        legacy_replacement: None,
    },
    FieldProfile {
        name: "triggers",
        shape: FieldShape::List,
        required_for: &[],
        recommended_for: &[ProfileNodeKind::Skill],
        legacy_replacement: Some("aliases"),
    },
    FieldProfile {
        name: "type",
        shape: FieldShape::Scalar,
        required_for: &[],
        recommended_for: ANY,
        legacy_replacement: None,
    },
    FieldProfile {
        name: "updated",
        shape: FieldShape::Scalar,
        required_for: &[],
        recommended_for: &[],
        legacy_replacement: None,
    },
    FieldProfile {
        name: "uses",
        shape: FieldShape::List,
        required_for: &[],
        recommended_for: &[],
        legacy_replacement: None,
    },
];

const VALID_STATUSES: &[&str] = &["active", "draft", "archived", "deprecated"];

const VALID_KINDS: &[&str] = &[
    "agent", "claim", "doc", "flow", "function", "module", "skill", "trait", "type",
];

const LEGACY_KIND_VALUES: &[LegacyValueProfile] = &[
    LegacyValueProfile {
        field: "type",
        value: "specialist",
        replacement: "agent",
    },
    LegacyValueProfile {
        field: "kind",
        value: "specialist",
        replacement: "agent",
    },
    LegacyValueProfile {
        field: "type",
        value: "workflow",
        replacement: "flow",
    },
    LegacyValueProfile {
        field: "kind",
        value: "workflow",
        replacement: "flow",
    },
    LegacyValueProfile {
        field: "type",
        value: "archetype",
        replacement: "flow",
    },
    LegacyValueProfile {
        field: "kind",
        value: "archetype",
        replacement: "flow",
    },
];

pub const AUN_FRONTMATTER_PROFILE: AunFrontmatterProfile = AunFrontmatterProfile {
    fields: FIELDS,
    valid_statuses: VALID_STATUSES,
    valid_kinds: VALID_KINDS,
    legacy_kind_values: LEGACY_KIND_VALUES,
};

impl AunFrontmatterProfile {
    pub fn field(&self, name: &str) -> Option<&'static FieldProfile> {
        self.fields.iter().find(|field| field.name == name)
    }

    pub fn is_known_field(&self, name: &str) -> bool {
        self.field(name).is_some()
    }

    pub fn fields_with_shape(&self, shape: FieldShape) -> impl Iterator<Item = &'static str> + '_ {
        self.fields
            .iter()
            .filter(move |field| field.shape == shape)
            .map(|field| field.name)
    }

    pub fn normalize_status(&self, raw: &str) -> Option<String> {
        let normalized = raw.trim().to_ascii_lowercase();
        self.valid_statuses
            .contains(&normalized.as_str())
            .then_some(normalized)
    }

    pub fn normalize_kind(&self, raw: &str) -> Option<String> {
        let normalized = Kind::normalize(raw);
        (normalized != Kind::Unknown).then(|| kind_label(&normalized))
    }
}

pub fn aun_frontmatter_profile() -> &'static AunFrontmatterProfile {
    &AUN_FRONTMATTER_PROFILE
}

pub fn kind_label(kind: &Kind) -> String {
    serde_json::to_value(kind)
        .ok()
        .and_then(|v| v.as_str().map(String::from))
        .unwrap_or_else(|| "unknown".into())
}
