use std::collections::HashMap;
use std::path::PathBuf;

use crate::core::{EntityId, SystemError};
use crate::runtime::World;

use super::solver::{ManifestSolver, SolverError, ResolvedScene};
use super::factory::{ComponentRegistry, FactoryError};
use super::manifest::{load_scene_manifest, ManifestLoaderError};

#[derive(Debug, thiserror::Error)]
pub enum SceneError {
    #[error("Manifest loader error: {0}")]
    ManifestLoader(#[from] ManifestLoaderError),
    #[error("Solver error: {0}")]
    Solver(#[from] SolverError),
    #[error("Factory error: {0}")]
    Factory(#[from] FactoryError),
    #[error("System error: {0}")]
    System(#[from] SystemError),
    #[error("Scene not found: {0}")]
    SceneNotFound(String),
}

pub struct SceneManager {
    manifest_solver: ManifestSolver,
    component_registry: ComponentRegistry,
    current_scene: Option<String>,
    scene_entities: HashMap<String, Vec<EntityId>>,
}

impl SceneManager {
    pub fn new<P: Into<PathBuf>>(base_path: P) -> Self {
        Self {
            manifest_solver: ManifestSolver::new(base_path),
            component_registry: ComponentRegistry::new(),
            current_scene: None,
            scene_entities: HashMap::new(),
        }
    }
    
    pub fn load_scene(&mut self, scene_name: &str, world: &mut World) -> Result<(), SceneError> {
        // 1. 기존 씬 언로드
        self.unload_current_scene(world)?;
        
        // 2. 씬 매니페스트 로드
        let scene_path = format!("world/scenes/{}.yaml", scene_name);
        let scene_manifest = load_scene_manifest(scene_path)?;
        
        // 3. 매니페스트 해석
        let resolved = self.manifest_solver.resolve_scene(&scene_manifest)?;
        
        // 4. 엔티티들 생성
        let entity_ids = self.instantiate_entities(&resolved, world)?;
        
        // 5. 추적 정보 업데이트
        self.scene_entities.insert(scene_name.to_string(), entity_ids);
        self.current_scene = Some(scene_name.to_string());
        
        Ok(())
    }
    
    pub fn unload_current_scene(&mut self, world: &mut World) -> Result<(), SceneError> {
        if let Some(current_scene) = &self.current_scene {
            if let Some(entity_ids) = self.scene_entities.remove(current_scene) {
                for entity_id in entity_ids {
                    world.destroy_entity(entity_id);
                }
            }
            self.current_scene = None;
        }
        Ok(())
    }
    
    pub fn transition_to_scene(&mut self, scene_name: &str, world: &mut World) -> Result<(), SceneError> {
        self.load_scene(scene_name, world)
    }
    
    pub fn current_scene(&self) -> Option<&str> {
        self.current_scene.as_deref()
    }
    
    fn instantiate_entities(&self, resolved: &ResolvedScene, world: &mut World) -> Result<Vec<EntityId>, SceneError> {
        let mut entity_ids = Vec::new();
        
        for (_entity_name, components) in &resolved.entities {
            let entity_id = world.create_entity();
            
            if let Some(entity) = world.get_entity_mut(entity_id) {
                for (component_name, component_data) in components.iter() {
                    let component = self.component_registry.create(component_name, component_data)?;
                    entity.add_component_boxed(component);
                }
            }
            
            entity_ids.push(entity_id);
        }
        
        Ok(entity_ids)
    }
}