use crate::{
    invocation::{SkillContext, SkillInput},
    outcome::SkillOutcome,
    skill::{Skill, SkillId},
};
use prism::index::incremental::hash_file;
use prism::{
    extract, index::ProjectIndex, ingestion::scanner::DirectoryScanner, parse::ParsedUnit,
};
use serde_json::json;
use std::time::Instant;

pub struct PrismSkill;

impl Skill for PrismSkill {
    fn id(&self) -> SkillId {
        SkillId("prism")
    }
    fn display_name(&self) -> &str {
        "Prism"
    }

    fn input_schema(&self) -> serde_json::Value {
        json!({
            "type": "object",
            "properties": {
                "root": { "type": "string" },
                "force_full": { "type": "boolean", "default": false },
                "max_files": { "type": "integer", "default": 500 }
            },
            "required": ["root"]
        })
    }

    fn output_schema(&self) -> serde_json::Value {
        json!({ "type": "object", "properties": { "files_parsed": { "type": "integer" }, "symbols_extracted": { "type": "integer" }, "duration_ms": { "type": "integer" } } })
    }

    fn execute(&self, input: SkillInput, _ctx: &SkillContext) -> anyhow::Result<SkillOutcome> {
        let root = input.get_str("root").unwrap_or(".").to_string();
        let max_files = input.get_u64("max_files").unwrap_or(500) as usize;
        let start = Instant::now();

        let scanner = DirectoryScanner::new();
        let files = scanner
            .scan(std::path::Path::new(&root))
            .unwrap_or_default();
        let files = &files[..max_files.min(files.len())];

        let mut index = ProjectIndex::new(&root);
        let mut symbols_total = 0usize;

        for path in files {
            let content = std::fs::read_to_string(path).unwrap_or_default();
            let hash = hash_file(&content);
            let unit = ParsedUnit::new(path.to_string_lossy().to_string(), content);
            let map = extract::extract(&unit);
            symbols_total += map.symbols.len();
            index.add_symbols(&map, &hash);
        }

        let duration_ms = start.elapsed().as_millis() as u64;

        Ok(SkillOutcome::success(
            "prism",
            json!({
                "files_parsed": files.len(),
                "symbols_extracted": symbols_total,
                "index_size_bytes": 0,
                "duration_ms": duration_ms
            }),
        ))
    }
}
