use crate::{
    invocation::{SkillContext, SkillInput},
    outcome::SkillOutcome,
    skill::{Skill, SkillId},
};
use anyhow::Result;
use prism::{extract, parse::ParsedUnit};
use serde_json::{json, Value};

pub struct ChiselSkill;

impl Skill for ChiselSkill {
    fn id(&self) -> SkillId {
        SkillId("chisel")
    }
    fn display_name(&self) -> &str {
        "Chisel"
    }

    fn input_schema(&self) -> serde_json::Value {
        json!({
            "type": "object",
            "properties": {
                "paths": { "type": "array", "items": { "type": "string" } },
                "filter_exported": { "type": "boolean", "default": false },
                "format": { "type": "string", "enum": ["compact", "json"], "default": "compact" }
            },
            "required": ["paths"]
        })
    }

    fn output_schema(&self) -> serde_json::Value {
        json!({ "type": "object", "properties": { "symbols": { "type": "array" }, "total_count": { "type": "integer" } } })
    }

    fn execute(&self, input: SkillInput, _ctx: &SkillContext) -> Result<SkillOutcome> {
        let paths = input
            .params
            .get("paths")
            .and_then(|v| v.as_array())
            .map(|arr| {
                arr.iter()
                    .filter_map(|v| v.as_str().map(|s| s.to_string()))
                    .collect::<Vec<_>>()
            })
            .unwrap_or_default();

        let filter_exported = input.get_bool("filter_exported").unwrap_or(false);
        let mut all_symbols: Vec<Value> = Vec::new();

        for path in &paths {
            let content = std::fs::read_to_string(path).unwrap_or_default();
            let unit = ParsedUnit::new(path.clone(), content);
            let map = extract::extract(&unit);

            for sym in map.symbols {
                if filter_exported && !sym.is_exported {
                    continue;
                }
                all_symbols.push(json!({
                    "name": sym.name,
                    "kind": format!("{:?}", sym.kind),
                    "file": path,
                    "is_exported": sym.is_exported
                }));
            }
        }

        let total = all_symbols.len();
        Ok(SkillOutcome::success(
            "chisel",
            json!({ "symbols": all_symbols, "total_count": total }),
        ))
    }
}
