#![allow(dead_code)]

//! Who screen actions — fetch people-intelligence data from the local database.
//!
//! Each function wraps a `query_*` function from `lore::cli::commands::who`
//! and returns the appropriate [`WhoResult`] variant.

use anyhow::Result;
use rusqlite::Connection;

use lore::cli::commands::who;
use lore::core::config::ScoringConfig;
use lore::core::who_types::WhoResult;

/// Default limit for result rows in TUI who queries.
const DEFAULT_LIMIT: usize = 20;

/// Default time window: 6 months in milliseconds.
const SIX_MONTHS_MS: i64 = 180 * 24 * 60 * 60 * 1000;

/// Fetch expert results for a file path.
pub fn fetch_who_expert(
    conn: &Connection,
    path: &str,
    project_id: Option<i64>,
    scoring: &ScoringConfig,
    now_ms: i64,
) -> Result<WhoResult> {
    let since_ms = now_ms - SIX_MONTHS_MS;
    let result = who::query_expert(
        conn,
        path,
        project_id,
        since_ms,
        now_ms,
        DEFAULT_LIMIT,
        scoring,
        false, // detail
        false, // explain_score
        false, // include_bots
    )?;
    Ok(WhoResult::Expert(result))
}

/// Fetch workload summary for a username.
pub fn fetch_who_workload(
    conn: &Connection,
    username: &str,
    project_id: Option<i64>,
    include_closed: bool,
) -> Result<WhoResult> {
    let result = who::query_workload(
        conn,
        username,
        project_id,
        None, // since_ms — show all for workload
        DEFAULT_LIMIT,
        include_closed,
    )?;
    Ok(WhoResult::Workload(result))
}

/// Fetch review activity breakdown for a username.
pub fn fetch_who_reviews(
    conn: &Connection,
    username: &str,
    project_id: Option<i64>,
    now_ms: i64,
) -> Result<WhoResult> {
    let since_ms = now_ms - SIX_MONTHS_MS;
    let result = who::query_reviews(conn, username, project_id, since_ms)?;
    Ok(WhoResult::Reviews(result))
}

/// Fetch recent active (unresolved) discussions.
pub fn fetch_who_active(
    conn: &Connection,
    project_id: Option<i64>,
    include_closed: bool,
    now_ms: i64,
) -> Result<WhoResult> {
    // Active mode default window: 7 days.
    let seven_days_ms: i64 = 7 * 24 * 60 * 60 * 1000;
    let since_ms = now_ms - seven_days_ms;
    let result = who::query_active(conn, project_id, since_ms, DEFAULT_LIMIT, include_closed)?;
    Ok(WhoResult::Active(result))
}

/// Fetch overlap (shared file knowledge) for a path.
pub fn fetch_who_overlap(
    conn: &Connection,
    path: &str,
    project_id: Option<i64>,
    now_ms: i64,
) -> Result<WhoResult> {
    let since_ms = now_ms - SIX_MONTHS_MS;
    let result = who::query_overlap(conn, path, project_id, since_ms, DEFAULT_LIMIT)?;
    Ok(WhoResult::Overlap(result))
}

#[cfg(test)]
mod tests {
    use super::*;

    /// Minimal schema for who queries (matches the real DB schema).
    fn create_who_schema(conn: &Connection) {
        conn.execute_batch(
            "
            CREATE TABLE projects (
                id INTEGER PRIMARY KEY,
                gitlab_project_id INTEGER UNIQUE NOT NULL,
                path_with_namespace TEXT NOT NULL
            );
            CREATE TABLE issues (
                id INTEGER PRIMARY KEY,
                gitlab_id INTEGER UNIQUE NOT NULL,
                project_id INTEGER NOT NULL,
                iid INTEGER NOT NULL,
                title TEXT,
                state TEXT NOT NULL,
                author_username TEXT,
                created_at INTEGER NOT NULL,
                updated_at INTEGER NOT NULL,
                last_seen_at INTEGER NOT NULL
            );
            CREATE TABLE merge_requests (
                id INTEGER PRIMARY KEY,
                gitlab_id INTEGER UNIQUE NOT NULL,
                project_id INTEGER NOT NULL,
                iid INTEGER NOT NULL,
                title TEXT,
                state TEXT,
                author_username TEXT,
                draft INTEGER NOT NULL DEFAULT 0,
                created_at INTEGER,
                updated_at INTEGER,
                merged_at INTEGER,
                closed_at INTEGER,
                last_seen_at INTEGER NOT NULL
            );
            CREATE TABLE issue_assignees (
                issue_id INTEGER NOT NULL,
                username TEXT NOT NULL,
                PRIMARY KEY(issue_id, username)
            );
            CREATE TABLE mr_reviewers (
                merge_request_id INTEGER NOT NULL,
                username TEXT NOT NULL,
                PRIMARY KEY(merge_request_id, username)
            );
            CREATE TABLE mr_file_changes (
                id INTEGER PRIMARY KEY,
                merge_request_id INTEGER NOT NULL,
                project_id INTEGER NOT NULL,
                new_path TEXT NOT NULL,
                old_path TEXT,
                change_type TEXT NOT NULL
            );
            CREATE TABLE discussions (
                id INTEGER PRIMARY KEY,
                gitlab_discussion_id TEXT NOT NULL,
                project_id INTEGER NOT NULL,
                noteable_type TEXT NOT NULL,
                issue_id INTEGER,
                merge_request_id INTEGER,
                resolvable INTEGER NOT NULL DEFAULT 0,
                resolved INTEGER NOT NULL DEFAULT 0,
                last_note_at INTEGER NOT NULL DEFAULT 0,
                last_seen_at INTEGER NOT NULL
            );
            CREATE TABLE notes (
                id INTEGER PRIMARY KEY,
                gitlab_id INTEGER UNIQUE NOT NULL,
                discussion_id INTEGER NOT NULL,
                project_id INTEGER NOT NULL,
                is_system INTEGER NOT NULL DEFAULT 0,
                author_username TEXT,
                body TEXT,
                note_type TEXT,
                position_new_path TEXT,
                position_old_path TEXT,
                created_at INTEGER NOT NULL,
                updated_at INTEGER NOT NULL,
                last_seen_at INTEGER NOT NULL
            );
            -- Indexes needed by who queries
            CREATE INDEX idx_notes_diffnote_path_created
                ON notes(position_new_path, created_at)
                WHERE note_type = 'DiffNote' AND is_system = 0;
            CREATE INDEX idx_notes_old_path_author
                ON notes(position_old_path, author_username)
                WHERE note_type = 'DiffNote' AND is_system = 0;
            CREATE INDEX idx_mfc_new_path_project_mr
                ON mr_file_changes(new_path, project_id, merge_request_id);
            CREATE INDEX idx_mfc_old_path_project_mr
                ON mr_file_changes(old_path, project_id, merge_request_id);
            ",
        )
        .expect("create who schema");
    }

    fn default_scoring() -> ScoringConfig {
        ScoringConfig::default()
    }

    fn now_ms() -> i64 {
        1_700_000_000_000 // Fixed timestamp for deterministic tests.
    }

    #[test]
    fn test_fetch_who_expert_empty_db_returns_empty() {
        let conn = Connection::open_in_memory().unwrap();
        create_who_schema(&conn);

        let result = fetch_who_expert(&conn, "src/", None, &default_scoring(), now_ms()).unwrap();
        match result {
            WhoResult::Expert(expert) => {
                assert!(expert.experts.is_empty());
                assert!(!expert.truncated);
            }
            _ => panic!("Expected Expert variant"),
        }
    }

    #[test]
    fn test_fetch_who_workload_empty_db_returns_empty() {
        let conn = Connection::open_in_memory().unwrap();
        create_who_schema(&conn);

        let result = fetch_who_workload(&conn, "alice", None, false).unwrap();
        match result {
            WhoResult::Workload(wl) => {
                assert_eq!(wl.username, "alice");
                assert!(wl.assigned_issues.is_empty());
                assert!(wl.authored_mrs.is_empty());
            }
            _ => panic!("Expected Workload variant"),
        }
    }

    #[test]
    fn test_fetch_who_reviews_empty_db_returns_empty() {
        let conn = Connection::open_in_memory().unwrap();
        create_who_schema(&conn);

        let result = fetch_who_reviews(&conn, "alice", None, now_ms()).unwrap();
        match result {
            WhoResult::Reviews(rev) => {
                assert_eq!(rev.username, "alice");
                assert_eq!(rev.total_diffnotes, 0);
            }
            _ => panic!("Expected Reviews variant"),
        }
    }

    #[test]
    fn test_fetch_who_active_empty_db_returns_empty() {
        let conn = Connection::open_in_memory().unwrap();
        create_who_schema(&conn);

        let result = fetch_who_active(&conn, None, false, now_ms()).unwrap();
        match result {
            WhoResult::Active(active) => {
                assert!(active.discussions.is_empty());
                assert_eq!(active.total_unresolved_in_window, 0);
            }
            _ => panic!("Expected Active variant"),
        }
    }

    #[test]
    fn test_fetch_who_overlap_empty_db_returns_empty() {
        let conn = Connection::open_in_memory().unwrap();
        create_who_schema(&conn);

        let result = fetch_who_overlap(&conn, "src/", None, now_ms()).unwrap();
        match result {
            WhoResult::Overlap(overlap) => {
                assert!(overlap.users.is_empty());
                assert!(!overlap.truncated);
            }
            _ => panic!("Expected Overlap variant"),
        }
    }
}
