use crate::ThreadId;
use crate::core::detector::GLOBAL_DETECTOR;
use crate::core::logger;
use crate::core::{Detector, Events};

impl Detector {
    /// Register a thread spawn
    ///
    /// This method is called when a new thread is created. It records the thread
    /// in the wait-for graph and establishes parent-child relationships for proper
    /// resource tracking.
    ///
    /// # Arguments
    /// * `thread_id` - ID of the newly spawned thread
    /// * `parent_id` - Optional ID of the parent thread that created this thread
    pub fn spawn_thread(&mut self, thread_id: ThreadId, parent_id: Option<ThreadId>) {
        logger::log_thread_event(thread_id, parent_id, Events::ThreadSpawn);

        // Ensure node exists in the wait-for graph
        self.wait_for_graph.edges.entry(thread_id).or_default();
    }

    /// Register a thread exit
    ///
    /// This method is called when a thread is about to exit. It cleans up resources
    /// associated with the thread and updates the wait-for graph.
    ///
    /// # Arguments
    /// * `thread_id` - ID of the exiting thread
    pub fn exit_thread(&mut self, thread_id: ThreadId) {
        logger::log_thread_event(thread_id, None, Events::ThreadExit);

        // remove thread and its edges from the wait-for graph
        self.wait_for_graph.remove_thread(thread_id);
        // no more held locks
        self.thread_holds.remove(&thread_id);

        // Note: We don't clean up cv_woken, thread_wait_cv, or thread_waits_for here
        // because these might be needed for deadlock detection even after thread exit.
        // This is a design choice - we prioritize correctness over immediate cleanup.
    }
}

/// Register a thread spawn with the global detector
///
/// # Arguments
/// * `thread_id` - ID of the spawned thread
/// * `parent_id` - Optional ID of the parent thread that created this thread
pub fn spawn_thread(thread_id: ThreadId, parent_id: Option<ThreadId>) {
    let mut detector = GLOBAL_DETECTOR.lock();
    detector.spawn_thread(thread_id, parent_id);
}

/// Register a thread exit with the global detector
///
/// # Arguments
/// * `thread_id` - ID of the exiting thread
pub fn exit_thread(thread_id: ThreadId) {
    let mut detector = GLOBAL_DETECTOR.lock();
    detector.exit_thread(thread_id);
}
