use crate::db::DbPool;
use chrono::{TimeDelta, Utc};
use uuid::Uuid;

pub fn create_refresh_token(db: &DbPool, pool_id: &str, username: &str) -> rusqlite::Result<String> {
    let conn = db.lock().unwrap();
    let token = Uuid::new_v4().to_string();
    let now = Utc::now();
    let expires = now + TimeDelta::days(30);
    conn.execute(
        "INSERT INTO refresh_tokens (token, pool_id, username, created_at, expires_at) VALUES (?1, ?2, ?3, ?4, ?5)",
        rusqlite::params![token, pool_id, username, now.to_rfc3339(), expires.to_rfc3339()],
    )?;
    Ok(token)
}

pub struct RefreshTokenInfo {
    pub pool_id: String,
    pub username: String,
}

pub fn validate_refresh_token(db: &DbPool, token: &str) -> rusqlite::Result<Option<RefreshTokenInfo>> {
    let conn = db.lock().unwrap();
    let now = Utc::now().to_rfc3339();
    let mut stmt = conn.prepare(
        "SELECT pool_id, username FROM refresh_tokens WHERE token = ?1 AND expires_at > ?2"
    )?;
    let mut rows = stmt.query(rusqlite::params![token, now])?;
    match rows.next()? {
        Some(row) => Ok(Some(RefreshTokenInfo {
            pool_id: row.get(0)?,
            username: row.get(1)?,
        })),
        None => Ok(None),
    }
}

pub fn delete_user_tokens(db: &DbPool, pool_id: &str, username: &str) -> rusqlite::Result<()> {
    let conn = db.lock().unwrap();
    conn.execute(
        "DELETE FROM refresh_tokens WHERE pool_id = ?1 AND username = ?2",
        rusqlite::params![pool_id, username],
    )?;
    Ok(())
}

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

    fn setup() -> DbPool {
        let pool = db::connect_in_memory().unwrap();
        db::run_migrations(&pool).unwrap();
        db::pools::create(&pool, "us-east-1_test", "Test", &serde_json::json!({})).unwrap();
        db::users::create(&pool, "us-east-1_test", "alice", None, "CONFIRMED", &[]).unwrap();
        pool
    }

    #[test]
    fn test_create_and_validate_refresh_token() {
        let db = setup();
        let token = create_refresh_token(&db, "us-east-1_test", "alice").unwrap();
        let info = validate_refresh_token(&db, &token).unwrap().unwrap();
        assert_eq!(info.pool_id, "us-east-1_test");
        assert_eq!(info.username, "alice");
    }

    #[test]
    fn test_invalid_token_returns_none() {
        let db = setup();
        assert!(validate_refresh_token(&db, "bogus-token").unwrap().is_none());
    }

    #[test]
    fn test_delete_user_tokens() {
        let db = setup();
        let token = create_refresh_token(&db, "us-east-1_test", "alice").unwrap();
        delete_user_tokens(&db, "us-east-1_test", "alice").unwrap();
        assert!(validate_refresh_token(&db, &token).unwrap().is_none());
    }
}
