use jsonschema::{JSONSchema, ValidationError};
use serde_json::Value;
use std::collections::HashMap;

pub struct Validator {
    schemas: HashMap<String, JSONSchema>,
}

impl Validator {
    pub fn new() -> Self {
        let mut schemas = HashMap::new();

        // Generate schemas for each type
        schemas.insert("h-entry".to_string(), JSONSchema::compile(&crate::schemas::generate_schema::<crate::schemas::HEntry>()).unwrap());
        schemas.insert("h-review".to_string(), JSONSchema::compile(&crate::schemas::generate_schema::<crate::schemas::HReview>()).unwrap());
        schemas.insert("h-feed".to_string(), JSONSchema::compile(&crate::schemas::generate_schema::<crate::schemas::HFeed>()).unwrap());
        schemas.insert("h-item".to_string(), JSONSchema::compile(&crate::schemas::generate_schema::<crate::schemas::HItem>()).unwrap());

        Self { schemas }
    }

    pub fn validate(&self, jf2: &Value, source_map: &HashMap<String, Vec<String>>) -> (Vec<String>, Vec<String>) {
        let mut invalid_ids = Vec::new();
        let mut errors = Vec::new();

        // Validate top-level items
        if let Some(items) = jf2.get("items").and_then(|i| i.as_array()) {
            for (item_idx, item) in items.iter().enumerate() {
                if let Some(types) = item.get("type").and_then(|t| t.as_array()) {
                    for type_val in types {
                        if let Some(type_str) = type_val.as_str() {
                            if let Some(schema) = self.schemas.get(type_str) {
                                let result = schema.validate(item);
                                if let Err(validation_errors) = result {
                                    // If there are any validation errors, mark the whole item as invalid
                                    let item_path = format!("items[{}]", item_idx);
                                    if let Some(ids) = source_map.get(&item_path) {
                                        invalid_ids.extend(ids.clone());
                                    }
                                    for error in validation_errors {
                                        errors.push(error.to_string());
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }

        (invalid_ids, errors)
    }

    pub fn get_schema(&self, type_name: &str) -> Option<&JSONSchema> {
        self.schemas.get(type_name)
    }
}