use crate::test_common::{HttpClient, TestContext, login, refresh_token, validate_uuid};
use crate::test_report::{TestSuite, TestCase, TestStep, TestStatus, Severity};
use serde::{Deserialize, Serialize};
use std::time::Instant;

pub fn run_auth_tests() -> TestSuite {
    let mut suite = TestSuite::new(
        "ERP-AUTH Module Integration Tests",
        "Complete authentication and authorization flow testing including login, token refresh, logout, user management, role management, and organization management"
    );

    let runtime = tokio::runtime::Runtime::new().unwrap();
    let client = HttpClient::new("http://localhost:3000");

    let mut ctx = TestContext::new();

    runtime.block_on(async {
        test_auth_01_login_success(&client, &mut ctx, &mut suite);
        test_auth_02_login_invalid_password(&client, &mut ctx, &mut suite);
        test_auth_03_login_missing_fields(&client, &mut ctx, &mut suite);
        test_auth_04_sql_injection_attempt(&client, &mut ctx, &mut suite);
        test_auth_05_token_refresh_success(&client, &mut ctx, &mut suite);
        test_auth_06_token_refresh_reuse_detection(&client, &mut ctx, &mut suite);
        test_auth_07_logout_success(&client, &mut ctx, &mut suite);
        test_auth_08_change_password(&client, &mut ctx, &mut suite);
        test_auth_09_change_password_wrong_old(&client, &mut ctx, &mut suite);

        test_user_01_list_users(&client, &mut ctx, &mut suite);
        test_user_02_list_users_with_pagination(&client, &mut ctx, &mut suite);
        test_user_03_list_users_search(&client, &mut ctx, &mut suite);
        test_user_04_create_user(&client, &mut ctx, &mut suite);
        test_user_05_create_user_duplicate_username(&client, &mut ctx, &mut suite);
        test_user_06_create_user_missing_fields(&client, &mut ctx, &mut suite);
        test_user_07_create_user_weak_password(&client, &mut ctx, &mut suite);
        test_user_08_get_user(&client, &mut ctx, &mut suite);
        test_user_09_get_user_invalid_id(&client, &mut ctx, &mut suite);
        test_user_10_update_user(&client, &mut ctx, &mut suite);
        test_user_11_delete_user(&client, &mut ctx, &mut suite);

        test_role_01_list_roles(&client, &mut ctx, &mut suite);
        test_role_02_create_role(&client, &mut ctx, &mut suite);
        test_role_03_create_role_duplicate_code(&client, &mut ctx, &mut suite);
        test_role_04_assign_permissions(&client, &mut ctx, &mut suite);
        test_role_05_get_role_permissions(&client, &mut ctx, &mut suite);
        test_role_06_delete_role(&client, &mut ctx, &mut suite);

        test_org_01_list_organizations(&client, &mut ctx, &mut suite);
        test_org_02_create_organization(&client, &mut ctx, &mut suite);
        test_org_03_create_sub_organization(&client, &mut ctx, &mut suite);
        test_org_04_update_organization(&client, &mut ctx, &mut suite);

        test_dept_01_create_department(&client, &mut ctx, &mut suite);
        test_dept_02_list_departments(&client, &mut ctx, &mut suite);
    });

    suite
}

fn test_auth_01_login_success(client: &HttpClient, ctx: &mut TestContext, suite: &mut TestSuite) {
    let mut case = TestCase::new("AUTH-01", "Login - Valid Credentials", "Authentication");
    case.severity = Severity::Critical;
    case.expected_result = "HTTP 200, access_token and refresh_token returned".to_string();

    let step1 = TestStep::new(1, "POST /api/v1/auth/login with valid credentials", "HTTP 200 response");
    let start = Instant::now();
    let result = client.post("/api/v1/auth/login", &serde_json::json!({
        "username": "admin",
        "password": "Admin@2026"
    }), None).await;
    let elapsed = start.elapsed().as_millis() as u64;
    let mut step1 = step1.with_actual(&format!("HTTP {} - {:?}", result.status, result.body), elapsed);
    case.add_step(step1);

    if result.status == 200 {
        if let Ok(data) = parse_login_response(&result.body) {
            ctx.access_token = data.access_token.clone();
            ctx.refresh_token = data.refresh_token.clone();
            case.actual_result = format!("access_token length: {}, refresh_token length: {}", data.access_token.len(), data.refresh_token.len());
            case.status = TestStatus::Pass;
            case.business_logic_verified = true;
        }
    } else {
        case.actual_result = format!("HTTP {}, body: {:?}", result.status, result.body);
        case.status = TestStatus::Fail;
        case.error_message = Some("Login failed with valid credentials".to_string());
    }

    suite.add_case(case);
}

fn test_auth_02_login_invalid_password(client: &HttpClient, _ctx: &mut TestContext, suite: &mut TestSuite) {
    let mut case = TestCase::new("AUTH-02", "Login - Invalid Password", "Authentication");
    case.severity = Severity::High;
    case.expected_result = "HTTP 401 Unauthorized".to_string();

    let step1 = TestStep::new(1, "POST /api/v1/auth/login with wrong password", "HTTP 401 response");
    let start = Instant::now();
    let result = client.post("/api/v1/auth/login", &serde_json::json!({
        "username": "admin",
        "password": "WrongPassword123!"
    }), None).await;
    let elapsed = start.elapsed().as_millis() as u64;
    let step1 = step1.with_actual(&format!("HTTP {}", result.status), elapsed);
    case.add_step(step1);

    if result.status == 401 {
        case.actual_result = "HTTP 401 - Authentication failed as expected".to_string();
        case.status = TestStatus::Pass;
        case.business_logic_verified = true;
    } else {
        case.actual_result = format!("Expected 401, got {}", result.status);
        case.status = TestStatus::Fail;
        case.error_message = Some("Should reject invalid password".to_string());
    }

    suite.add_case(case);
}

fn test_auth_03_login_missing_fields(client: &HttpClient, _ctx: &mut TestContext, suite: &mut TestSuite) {
    let mut case = TestCase::new("AUTH-03", "Login - Missing Required Fields", "Authentication");
    case.severity = Severity::Medium;
    case.expected_result = "HTTP 422 Validation Error".to_string();

    let result = client.post("/api/v1/auth/login", &serde_json::json!({
        "username": "admin"
    }), None).await;

    if result.status == 422 || result.status == 400 {
        case.actual_result = format!("HTTP {} - Validation error as expected", result.status);
        case.status = TestStatus::Pass;
        case.business_logic_verified = true;
    } else {
        case.actual_result = format!("Expected 422, got {}", result.status);
        case.status = TestStatus::Fail;
    }

    case.add_step(TestStep::new(1, "POST /api/v1/auth/login with missing password", "HTTP 422/400")
        .with_actual(&format!("HTTP {}", result.status), 0));

    suite.add_case(case);
}

fn test_auth_04_sql_injection_attempt(client: &HttpClient, _ctx: &mut TestContext, suite: &mut TestSuite) {
    let mut case = TestCase::new("AUTH-04", "Login - SQL Injection Attack Prevention", "Security");
    case.severity = Severity::Critical;
    case.expected_result = "HTTP 401 - Attack prevented".to_string();

    let result = client.post("/api/v1/auth/login", &serde_json::json!({
        "username": "admin' OR 1=1 --",
        "password": "anything"
    }), None).await;

    if result.status == 401 {
        case.actual_result = "HTTP 401 - SQL injection attack blocked".to_string();
        case.status = TestStatus::Pass;
        case.business_logic_verified = true;
    } else {
        case.actual_result = format!("Unexpected response: {}", result.status);
        case.status = TestStatus::Fail;
        case.error_message = Some("SQL injection may be possible".to_string());
    }

    case.add_step(TestStep::new(1, "POST /api/v1/auth/login with SQL injection payload", "HTTP 401")
        .with_actual(&format!("HTTP {}", result.status), 0));

    suite.add_case(case);
}

fn test_auth_05_token_refresh_success(client: &HttpClient, ctx: &mut TestContext, suite: &mut TestSuite) {
    let mut case = TestCase::new("AUTH-05", "Token Refresh - Valid Token", "Authentication");
    case.severity = Severity::Critical;
    case.expected_result = "HTTP 200, new access_token and refresh_token returned".to_string();

    if ctx.refresh_token.is_empty() {
        case.status = TestStatus::Blocked;
        case.error_message = Some("No refresh token available".to_string());
        suite.add_case(case);
        return;
    }

    let step1 = TestStep::new(1, "POST /api/v1/auth/refresh with valid token", "HTTP 200 with new tokens");
    let start = Instant::now();
    let result = client.post("/api/v1/auth/refresh", &serde_json::json!({
        "refresh_token": ctx.refresh_token
    }), None).await;
    let elapsed = start.elapsed().as_millis() as u64;
    let mut step1 = step1.with_actual(&format!("HTTP {}", result.status), elapsed);
    case.add_step(step1);

    if result.status == 200 {
        if let Ok(data) = parse_login_response(&result.body) {
            let old_token = ctx.access_token.clone();
            ctx.access_token = data.access_token.clone();
            ctx.refresh_token = data.refresh_token.clone();
            if old_token != ctx.access_token {
                case.actual_result = "Token rotated successfully".to_string();
                case.status = TestStatus::Pass;
                case.business_logic_verified = true;
            } else {
                case.actual_result = "Token did not rotate".to_string();
                case.status = TestStatus::Fail;
            }
        }
    } else {
        case.actual_result = format!("HTTP {} - {:?}", result.status, result.body);
        case.status = TestStatus::Fail;
    }

    suite.add_case(case);
}

fn test_auth_06_token_refresh_reuse_detection(client: &HttpClient, ctx: &mut TestContext, suite: &mut TestSuite) {
    let mut case = TestCase::new("AUTH-06", "Token Refresh - Reuse Detection (Rotation Security)", "Security");
    case.severity = Severity::Critical;
    case.expected_result = "Second use of old refresh token should be rejected".to_string();

    if ctx.refresh_token.is_empty() {
        case.status = TestStatus::Blocked;
        suite.add_case(case);
        return;
    }

    let old_refresh = ctx.refresh_token.clone();

    let result1 = client.post("/api/v1/auth/refresh", &serde_json::json!({
        "refresh_token": old_refresh
    }), None).await;

    if result1.status == 200 {
        if let Ok(data) = parse_login_response(&result1.body) {
            ctx.refresh_token = data.refresh_token;
        }
    }

    let result2 = client.post("/api/v1/auth/refresh", &serde_json::json!({
        "refresh_token": old_refresh
    }), None).await;

    if result2.status == 401 {
        case.actual_result = "Reused token was rejected - security verified".to_string();
        case.status = TestStatus::Pass;
        case.business_logic_verified = true;
    } else {
        case.actual_result = format!("Token reuse not detected: {}", result2.status);
        case.status = TestStatus::Fail;
        case.error_message = Some("Refresh token rotation security failed".to_string());
    }

    case.add_step(TestStep::new(1, "First refresh with token", "HTTP 200")
        .with_actual(&format!("HTTP {}", result1.status), 0));
    case.add_step(TestStep::new(2, "Second refresh with same token (reuse)", "HTTP 401")
        .with_actual(&format!("HTTP {}", result2.status), 0));

    suite.add_case(case);
}

fn test_auth_07_logout_success(client: &HttpClient, ctx: &mut TestContext, suite: &mut TestSuite) {
    let mut case = TestCase::new("AUTH-07", "Logout - Success", "Authentication");
    case.severity = Severity::Medium;
    case.expected_result = "HTTP 200 - Token invalidated".to_string();

    let result = client.post("/api/v1/auth/logout", &serde_json::json!({}), Some(&ctx.access_token)).await;

    if result.status == 200 {
        case.actual_result = "Logout successful".to_string();
        case.status = TestStatus::Pass;
        case.business_logic_verified = true;
    } else {
        case.actual_result = format!("HTTP {} - {:?}", result.status, result.body);
        case.status = TestStatus::Fail;
    }

    case.add_step(TestStep::new(1, "POST /api/v1/auth/logout", "HTTP 200")
        .with_actual(&format!("HTTP {}", result.status), 0));

    suite.add_case(case);
}

fn test_auth_08_change_password(client: &HttpClient, ctx: &mut TestContext, suite: &mut TestSuite) {
    let mut case = TestCase::new("AUTH-08", "Change Password - Success", "Authentication");
    case.severity = Severity::Critical;
    case.expected_result = "HTTP 200 - Password changed".to_string();

    let result = client.post("/api/v1/auth/change-password", &serde_json::json!({
        "old_password": "Admin@2026",
        "new_password": "NewAdmin@2026!"
    }), Some(&ctx.access_token)).await;

    if result.status == 200 {
        case.actual_result = "Password changed successfully".to_string();
        case.status = TestStatus::Pass;
        case.business_logic_verified = true;
    } else {
        case.actual_result = format!("HTTP {} - {:?}", result.status, result.body);
        case.status = TestStatus::Fail;
    }

    case.add_step(TestStep::new(1, "POST /api/v1/auth/change-password", "HTTP 200")
        .with_actual(&format!("HTTP {}", result.status), 0));

    suite.add_case(case);
}

fn test_auth_09_change_password_wrong_old(client: &HttpClient, ctx: &mut TestContext, suite: &mut TestSuite) {
    let mut case = TestCase::new("AUTH-09", "Change Password - Wrong Old Password", "Authentication");
    case.severity = Severity::High;
    case.expected_result = "HTTP 400/401 - Old password rejected".to_string();

    let result = client.post("/api/v1/auth/change-password", &serde_json::json!({
        "old_password": "WrongOldPass",
        "new_password": "AnotherNewPass@2026!"
    }), Some(&ctx.access_token)).await;

    if result.status == 400 || result.status == 401 {
        case.actual_result = "Wrong old password rejected".to_string();
        case.status = TestStatus::Pass;
        case.business_logic_verified = true;
    } else {
        case.actual_result = format!("Unexpected: {}", result.status);
        case.status = TestStatus::Fail;
    }

    case.add_step(TestStep::new(1, "POST /api/v1/auth/change-password with wrong old", "HTTP 400/401")
        .with_actual(&format!("HTTP {}", result.status), 0));

    suite.add_case(case);
}

fn test_user_01_list_users(client: &HttpClient, ctx: &mut TestContext, suite: &mut TestSuite) {
    let mut case = TestCase::new("USER-01", "List Users - Basic Pagination", "User Management");
    case.severity = Severity::High;
    case.expected_result = "HTTP 200, paginated user list returned".to_string();

    let result = client.get("/api/v1/users", Some(&ctx.access_token)).await;

    if result.status == 200 {
        if let Some((total, page, page_size)) = parse_pagination(&result.body) {
            case.actual_result = format!("total={}, page={}, page_size={}", total, page, page_size);
            case.status = TestStatus::Pass;
            case.business_logic_verified = true;
        } else {
            case.actual_result = "Invalid pagination format".to_string();
            case.status = TestStatus::Fail;
        }
    } else {
        case.actual_result = format!("HTTP {}", result.status);
        case.status = TestStatus::Fail;
    }

    case.add_step(TestStep::new(1, "GET /api/v1/users", "HTTP 200 with pagination")
        .with_actual(&format!("HTTP {} - {:?}", result.status, result.body), 0));

    suite.add_case(case);
}

fn test_user_02_list_users_with_pagination(client: &HttpClient, ctx: &mut TestContext, suite: &mut TestSuite) {
    let mut case = TestCase::new("USER-02", "List Users - Custom Page Size", "User Management");
    case.severity = Severity::Medium;
    case.expected_result = "HTTP 200, page_size=2 returned".to_string();

    let result = client.get("/api/v1/users?page=1&page_size=2", Some(&ctx.access_token)).await;

    if result.status == 200 {
        if let Some((_, page, page_size)) = parse_pagination(&result.body) {
            if page_size == 2 {
                case.actual_result = format!("page_size={} as requested", page_size);
                case.status = TestStatus::Pass;
                case.business_logic_verified = true;
            } else {
                case.actual_result = format!("Expected page_size=2, got {}", page_size);
                case.status = TestStatus::Fail;
            }
        } else {
            case.status = TestStatus::Fail;
        }
    } else {
        case.status = TestStatus::Fail;
    }

    case.add_step(TestStep::new(1, "GET /api/v1/users?page=1&page_size=2", "HTTP 200")
        .with_actual(&format!("HTTP {}", result.status), 0));

    suite.add_case(case);
}

fn test_user_03_list_users_search(client: &HttpClient, ctx: &mut TestContext, suite: &mut TestSuite) {
    let mut case = TestCase::new("USER-03", "List Users - Search Filter", "User Management");
    case.severity = Severity::Medium;
    case.expected_result = "HTTP 200, filtered results".to_string();

    let result = client.get("/api/v1/users?search=admin", Some(&ctx.access_token)).await;

    if result.status == 200 {
        case.actual_result = "Search filter applied".to_string();
        case.status = TestStatus::Pass;
        case.business_logic_verified = true;
    } else {
        case.actual_result = format!("HTTP {}", result.status);
        case.status = TestStatus::Fail;
    }

    case.add_step(TestStep::new(1, "GET /api/v1/users?search=admin", "HTTP 200")
        .with_actual(&format!("HTTP {}", result.status), 0));

    suite.add_case(case);
}

fn test_user_04_create_user(client: &HttpClient, ctx: &mut TestContext, suite: &mut TestSuite) {
    let mut case = TestCase::new("USER-04", "Create User - Valid Data", "User Management");
    case.severity = Severity::Critical;
    case.expected_result = "HTTP 200, user created with valid ID".to_string();

    let new_username = format!("test_user_{}", uuid::Uuid::new_v4().to_string().split('-').next().unwrap());
    let result = client.post("/api/v1/users", &serde_json::json!({
        "username": new_username,
        "password": "TestPass@2026",
        "display_name": "Test User",
        "email": "test@example.com",
        "phone": "13800138000"
    }), Some(&ctx.access_token)).await;

    if result.status == 200 {
        if let Some(user_id) = parse_id(&result.body) {
            ctx.store_resource("user", uuid::Uuid::parse_str(&user_id).unwrap_or(uuid::Uuid::nil()), &new_username);
            case.actual_result = format!("User created with ID: {}", user_id);
            case.status = TestStatus::Pass;
            case.business_logic_verified = true;
        } else {
            case.actual_result = "User ID not found in response".to_string();
            case.status = TestStatus::Fail;
        }
    } else {
        case.actual_result = format!("HTTP {} - {:?}", result.status, result.body);
        case.status = TestStatus::Fail;
    }

    case.add_step(TestStep::new(1, "POST /api/v1/users", "HTTP 200 with user_id")
        .with_actual(&format!("HTTP {} - {:?}", result.status, result.body), 0));

    suite.add_case(case);
}

fn test_user_05_create_user_duplicate_username(client: &HttpClient, ctx: &mut TestContext, suite: &mut TestSuite) {
    let mut case = TestCase::new("USER-05", "Create User - Duplicate Username", "User Management");
    case.severity = Severity::High;
    case.expected_result = "HTTP 409 Conflict".to_string();

    let result = client.post("/api/v1/users", &serde_json::json!({
        "username": "test_user_api",
        "password": "TestPass@2026",
        "display_name": "Duplicate User"
    }), Some(&ctx.access_token)).await;

    if result.status == 409 || result.status == 400 {
        case.actual_result = "Duplicate username rejected".to_string();
        case.status = TestStatus::Pass;
        case.business_logic_verified = true;
    } else {
        case.actual_result = format!("Expected 409/400, got {}", result.status);
        case.status = TestStatus::Fail;
    }

    case.add_step(TestStep::new(1, "POST /api/v1/users with duplicate username", "HTTP 409/400")
        .with_actual(&format!("HTTP {}", result.status), 0));

    suite.add_case(case);
}

fn test_user_06_create_user_missing_fields(client: &HttpClient, ctx: &mut TestContext, suite: &mut TestSuite) {
    let mut case = TestCase::new("USER-06", "Create User - Missing Required Fields", "User Management");
    case.severity = Severity::High;
    case.expected_result = "HTTP 422 Validation Error".to_string();

    let result = client.post("/api/v1/users", &serde_json::json!({
        "display_name": "No Username User"
    }), Some(&ctx.access_token)).await;

    if result.status == 422 || result.status == 400 {
        case.actual_result = "Validation error as expected".to_string();
        case.status = TestStatus::Pass;
        case.business_logic_verified = true;
    } else {
        case.actual_result = format!("Expected 422/400, got {}", result.status);
        case.status = TestStatus::Fail;
    }

    case.add_step(TestStep::new(1, "POST /api/v1/users with missing fields", "HTTP 422/400")
        .with_actual(&format!("HTTP {}", result.status), 0));

    suite.add_case(case);
}

fn test_user_07_create_user_weak_password(client: &HttpClient, ctx: &mut TestContext, suite: &mut TestSuite) {
    let mut case = TestCase::new("USER-07", "Create User - Weak Password Rejection", "User Management");
    case.severity = Severity::High;
    case.expected_result = "HTTP 400/422 - Weak password rejected".to_string();

    let result = client.post("/api/v1/users", &serde_json::json!({
        "username": "weak_pass_user",
        "password": "123",
        "display_name": "Weak Password User"
    }), Some(&ctx.access_token)).await;

    if result.status == 400 || result.status == 422 {
        case.actual_result = "Weak password rejected".to_string();
        case.status = TestStatus::Pass;
        case.business_logic_verified = true;
    } else {
        case.actual_result = format!("Password policy not enforced: {}", result.status);
        case.status = TestStatus::Fail;
    }

    case.add_step(TestStep::new(1, "POST /api/v1/users with weak password", "HTTP 400/422")
        .with_actual(&format!("HTTP {}", result.status), 0));

    suite.add_case(case);
}

fn test_user_08_get_user(client: &HttpClient, ctx: &mut TestContext, suite: &mut TestSuite) {
    let mut case = TestCase::new("USER-08", "Get User - By ID", "User Management");
    case.severity = Severity::High;
    case.expected_result = "HTTP 200, user data returned".to_string();

    if let Some(user_id) = ctx.get_resource("user", "test_user_api") {
        let result = client.get(&format!("/api/v1/users/{}", user_id), Some(&ctx.access_token)).await;

        if result.status == 200 {
            case.actual_result = "User retrieved successfully".to_string();
            case.status = TestStatus::Pass;
            case.business_logic_verified = true;
        } else {
            case.actual_result = format!("HTTP {}", result.status);
            case.status = TestStatus::Fail;
        }
    } else {
        case.status = TestStatus::Blocked;
        case.error_message = Some("No test user available".to_string());
    }

    case.add_step(TestStep::new(1, "GET /api/v1/users/{id}", "HTTP 200")
        .with_actual("Completed", 0));

    suite.add_case(case);
}

fn test_user_09_get_user_invalid_id(client: &HttpClient, ctx: &mut TestContext, suite: &mut TestSuite) {
    let mut case = TestCase::new("USER-09", "Get User - Invalid UUID", "User Management");
    case.severity = Severity::Medium;
    case.expected_result = "HTTP 404 Not Found".to_string();

    let result = client.get("/api/v1/users/00000000-0000-0000-0000-000000000000", Some(&ctx.access_token)).await;

    if result.status == 404 {
        case.actual_result = "Invalid UUID handled correctly".to_string();
        case.status = TestStatus::Pass;
        case.business_logic_verified = true;
    } else {
        case.actual_result = format!("Expected 404, got {}", result.status);
        case.status = TestStatus::Fail;
    }

    case.add_step(TestStep::new(1, "GET /api/v1/users/invalid-uuid", "HTTP 404")
        .with_actual(&format!("HTTP {}", result.status), 0));

    suite.add_case(case);
}

fn test_user_10_update_user(client: &HttpClient, ctx: &mut TestContext, suite: &mut TestSuite) {
    let mut case = TestCase::new("USER-10", "Update User - Valid Data", "User Management");
    case.severity = Severity::High;
    case.expected_result = "HTTP 200, user updated".to_string();

    if let Some(user_id) = ctx.get_resource("user", "test_user_api") {
        let result = client.put(&format!("/api/v1/users/{}", user_id), &serde_json::json!({
            "display_name": "Updated Test User"
        }), Some(&ctx.access_token)).await;

        if result.status == 200 {
            case.actual_result = "User updated successfully".to_string();
            case.status = TestStatus::Pass;
            case.business_logic_verified = true;
        } else {
            case.actual_result = format!("HTTP {}", result.status);
            case.status = TestStatus::Fail;
        }
    } else {
        case.status = TestStatus::Blocked;
    }

    case.add_step(TestStep::new(1, "PUT /api/v1/users/{id}", "HTTP 200")
        .with_actual("Completed", 0));

    suite.add_case(case);
}

fn test_user_11_delete_user(client: &HttpClient, ctx: &mut TestContext, suite: &mut TestSuite) {
    let mut case = TestCase::new("USER-11", "Delete User - Soft Delete", "User Management");
    case.severity = Severity::High;
    case.expected_result = "HTTP 200, user soft deleted".to_string();

    let new_username = format!("delete_test_{}", uuid::Uuid::new_v4().to_string().split('-').next().unwrap());
    let create_result = client.post("/api/v1/users", &serde_json::json!({
        "username": new_username,
        "password": "TestPass@2026",
        "display_name": "Delete Test User"
    }), Some(&ctx.access_token)).await;

    if create_result.status == 200 {
        if let Some(user_id) = parse_id(&create_result.body) {
            let delete_result = client.delete(&format!("/api/v1/users/{}", user_id), Some(&ctx.access_token)).await;

            if delete_result.status == 200 {
                case.actual_result = "User soft deleted".to_string();
                case.status = TestStatus::Pass;
                case.business_logic_verified = true;
            } else {
                case.actual_result = format!("Delete failed: {}", delete_result.status);
                case.status = TestStatus::Fail;
            }
        }
    } else {
        case.status = TestStatus::Blocked;
    }

    case.add_step(TestStep::new(1, "POST /api/v1/users", "HTTP 200")
        .with_actual("Created", 0));
    case.add_step(TestStep::new(2, "DELETE /api/v1/users/{id}", "HTTP 200")
        .with_actual("Completed", 0));

    suite.add_case(case);
}

fn test_role_01_list_roles(client: &HttpClient, ctx: &mut TestContext, suite: &mut TestSuite) {
    let mut case = TestCase::new("ROLE-01", "List Roles - Basic", "Role Management");
    case.severity = Severity::High;
    case.expected_result = "HTTP 200, role list returned".to_string();

    let result = client.get("/api/v1/roles", Some(&ctx.access_token)).await;

    if result.status == 200 {
        case.actual_result = "Roles listed".to_string();
        case.status = TestStatus::Pass;
        case.business_logic_verified = true;
    } else {
        case.actual_result = format!("HTTP {}", result.status);
        case.status = TestStatus::Fail;
    }

    case.add_step(TestStep::new(1, "GET /api/v1/roles", "HTTP 200")
        .with_actual(&format!("HTTP {}", result.status), 0));

    suite.add_case(case);
}

fn test_role_02_create_role(client: &HttpClient, ctx: &mut TestContext, suite: &mut TestSuite) {
    let mut case = TestCase::new("ROLE-02", "Create Role - Valid Data", "Role Management");
    case.severity = Severity::Critical;
    case.expected_result = "HTTP 200, role created".to_string();

    let role_code = format!("test_role_{}", uuid::Uuid::new_v4().to_string().split('-').next().unwrap());
    let result = client.post("/api/v1/roles", &serde_json::json!({
        "name": "Test Role",
        "code": &role_code,
        "description": "Integration test role"
    }), Some(&ctx.access_token)).await;

    if result.status == 200 {
        if let Some(role_id) = parse_id(&result.body) {
            ctx.store_resource("role", uuid::Uuid::parse_str(&role_id).unwrap_or(uuid::Uuid::nil()), &role_code);
            case.actual_result = format!("Role created: {}", role_id);
            case.status = TestStatus::Pass;
            case.business_logic_verified = true;
        }
    } else {
        case.actual_result = format!("HTTP {} - {:?}", result.status, result.body);
        case.status = TestStatus::Fail;
    }

    case.add_step(TestStep::new(1, "POST /api/v1/roles", "HTTP 200")
        .with_actual(&format!("HTTP {}", result.status), 0));

    suite.add_case(case);
}

fn test_role_03_create_role_duplicate_code(client: &HttpClient, ctx: &mut TestContext, suite: &mut TestSuite) {
    let mut case = TestCase::new("ROLE-03", "Create Role - Duplicate Code", "Role Management");
    case.severity = Severity::High;
    case.expected_result = "HTTP 409 Conflict".to_string();

    let result = client.post("/api/v1/roles", &serde_json::json!({
        "name": "Duplicate Role",
        "code": "admin",
        "description": "Should fail"
    }), Some(&ctx.access_token)).await;

    if result.status == 409 || result.status == 400 {
        case.actual_result = "Duplicate code rejected".to_string();
        case.status = TestStatus::Pass;
        case.business_logic_verified = true;
    } else {
        case.actual_result = format!("Expected 409, got {}", result.status);
        case.status = TestStatus::Fail;
    }

    case.add_step(TestStep::new(1, "POST /api/v1/roles with duplicate code", "HTTP 409")
        .with_actual(&format!("HTTP {}", result.status), 0));

    suite.add_case(case);
}

fn test_role_04_assign_permissions(client: &HttpClient, ctx: &mut TestContext, suite: &mut TestSuite) {
    let mut case = TestCase::new("ROLE-04", "Assign Permissions to Role", "Role Management");
    case.severity = Severity::Critical;
    case.expected_result = "HTTP 200, permissions assigned".to_string();

    if let Some(role_id) = ctx.get_resource("role", "test_role_api").or_else(|| {
        ctx.created_resources.get("role").and_then(|r| r.first()).map(|r| r.id)
    }) {
        let result = client.post(&format!("/api/v1/roles/{}/permissions", role_id), &serde_json::json!({
            "permission_codes": ["user.list", "user.create"]
        }), Some(&ctx.access_token)).await;

        if result.status == 200 {
            case.actual_result = "Permissions assigned".to_string();
            case.status = TestStatus::Pass;
            case.business_logic_verified = true;
        } else {
            case.actual_result = format!("HTTP {}", result.status);
            case.status = TestStatus::Fail;
        }
    } else {
        case.status = TestStatus::Blocked;
    }

    case.add_step(TestStep::new(1, "POST /api/v1/roles/{id}/permissions", "HTTP 200")
        .with_actual("Completed", 0));

    suite.add_case(case);
}

fn test_role_05_get_role_permissions(client: &HttpClient, ctx: &mut TestContext, suite: &mut TestSuite) {
    let mut case = TestCase::new("ROLE-05", "Get Role Permissions", "Role Management");
    case.severity = Severity::Medium;
    case.expected_result = "HTTP 200, permissions list returned".to_string();

    let result = client.get("/api/v1/roles", Some(&ctx.access_token)).await;

    if result.status == 200 {
        case.actual_result = "Permissions retrieved".to_string();
        case.status = TestStatus::Pass;
        case.business_logic_verified = true;
    } else {
        case.actual_result = format!("HTTP {}", result.status);
        case.status = TestStatus::Fail;
    }

    case.add_step(TestStep::new(1, "GET /api/v1/roles", "HTTP 200")
        .with_actual(&format!("HTTP {}", result.status), 0));

    suite.add_case(case);
}

fn test_role_06_delete_role(client: &HttpClient, ctx: &mut TestContext, suite: &mut TestSuite) {
    let mut case = TestCase::new("ROLE-06", "Delete Role - Soft Delete", "Role Management");
    case.severity = Severity::High;
    case.expected_result = "HTTP 200, role deleted".to_string();

    let role_code = format!("delete_role_{}", uuid::Uuid::new_v4().to_string().split('-').next().unwrap());
    let create_result = client.post("/api/v1/roles", &serde_json::json!({
        "name": "Delete Test Role",
        "code": &role_code,
        "description": "To be deleted"
    }), Some(&ctx.access_token)).await;

    if create_result.status == 200 {
        if let Some(role_id) = parse_id(&create_result.body) {
            let delete_result = client.delete(&format!("/api/v1/roles/{}", role_id), Some(&ctx.access_token)).await;

            if delete_result.status == 200 {
                case.actual_result = "Role deleted".to_string();
                case.status = TestStatus::Pass;
                case.business_logic_verified = true;
            } else {
                case.actual_result = format!("Delete failed: {}", delete_result.status);
                case.status = TestStatus::Fail;
            }
        }
    } else {
        case.status = TestStatus::Blocked;
    }

    case.add_step(TestStep::new(1, "POST /api/v1/roles", "HTTP 200")
        .with_actual("Created", 0));
    case.add_step(TestStep::new(2, "DELETE /api/v1/roles/{id}", "HTTP 200")
        .with_actual("Completed", 0));

    suite.add_case(case);
}

fn test_org_01_list_organizations(client: &HttpClient, ctx: &mut TestContext, suite: &mut TestSuite) {
    let mut case = TestCase::new("ORG-01", "List Organizations - Tree Structure", "Organization Management");
    case.severity = Severity::High;
    case.expected_result = "HTTP 200, org tree returned".to_string();

    let result = client.get("/api/v1/organizations", Some(&ctx.access_token)).await;

    if result.status == 200 {
        case.actual_result = "Organization tree retrieved".to_string();
        case.status = TestStatus::Pass;
        case.business_logic_verified = true;
    } else {
        case.actual_result = format!("HTTP {}", result.status);
        case.status = TestStatus::Fail;
    }

    case.add_step(TestStep::new(1, "GET /api/v1/organizations", "HTTP 200")
        .with_actual(&format!("HTTP {}", result.status), 0));

    suite.add_case(case);
}

fn test_org_02_create_organization(client: &HttpClient, ctx: &mut TestContext, suite: &mut TestSuite) {
    let mut case = TestCase::new("ORG-02", "Create Organization - Root Level", "Organization Management");
    case.severity = Severity::Critical;
    case.expected_result = "HTTP 200, org created".to_string();

    let org_name = format!("Test Org {}", uuid::Uuid::new_v4().to_string().split('-').next().unwrap());
    let result = client.post("/api/v1/organizations", &serde_json::json!({
        "name": &org_name,
        "code": format!("ORG_{}", uuid::Uuid::new_v4().to_string().split('-').next().unwrap()),
        "description": "Integration test org"
    }), Some(&ctx.access_token)).await;

    if result.status == 200 {
        if let Some(org_id) = parse_id(&result.body) {
            ctx.store_resource("organization", uuid::Uuid::parse_str(&org_id).unwrap_or(uuid::Uuid::nil()), &org_name);
            case.actual_result = format!("Organization created: {}", org_id);
            case.status = TestStatus::Pass;
            case.business_logic_verified = true;
        }
    } else {
        case.actual_result = format!("HTTP {} - {:?}", result.status, result.body);
        case.status = TestStatus::Fail;
    }

    case.add_step(TestStep::new(1, "POST /api/v1/organizations", "HTTP 200")
        .with_actual(&format!("HTTP {}", result.status), 0));

    suite.add_case(case);
}

fn test_org_03_create_sub_organization(client: &HttpClient, ctx: &mut TestContext, suite: &mut TestSuite) {
    let mut case = TestCase::new("ORG-03", "Create Sub-Organization - Hierarchical", "Organization Management");
    case.severity = Severity::High;
    case.expected_result = "HTTP 200, sub-org created under parent".to_string();

    let parent_id = ctx.get_resource("organization", "Test Org");
    if parent_id.is_none() {
        case.status = TestStatus::Blocked;
        case.error_message = Some("No parent org available".to_string());
        suite.add_case(case);
        return;
    }

    let sub_org_name = format!("Sub Org {}", uuid::Uuid::new_v4().to_string().split('-').next().unwrap());
    let result = client.post("/api/v1/organizations", &serde_json::json!({
        "name": &sub_org_name,
        "code": format!("SUB_{}", uuid::Uuid::new_v4().to_string().split('-').next().unwrap()),
        "parent_id": parent_id,
        "description": "Child organization"
    }), Some(&ctx.access_token)).await;

    if result.status == 200 {
        case.actual_result = "Sub-organization created".to_string();
        case.status = TestStatus::Pass;
        case.business_logic_verified = true;
    } else {
        case.actual_result = format!("HTTP {}", result.status);
        case.status = TestStatus::Fail;
    }

    case.add_step(TestStep::new(1, "POST /api/v1/organizations with parent_id", "HTTP 200")
        .with_actual(&format!("HTTP {}", result.status), 0));

    suite.add_case(case);
}

fn test_org_04_update_organization(client: &HttpClient, ctx: &mut TestContext, suite: &mut TestSuite) {
    let mut case = TestCase::new("ORG-04", "Update Organization", "Organization Management");
    case.severity = Severity::High;
    case.expected_result = "HTTP 200, org updated".to_string();

    if let Some(org_id) = ctx.get_resource("organization", "Test Org") {
        let result = client.put(&format!("/api/v1/organizations/{}", org_id), &serde_json::json!({
            "name": "Updated Test Org"
        }), Some(&ctx.access_token)).await;

        if result.status == 200 {
            case.actual_result = "Organization updated".to_string();
            case.status = TestStatus::Pass;
            case.business_logic_verified = true;
        } else {
            case.actual_result = format!("HTTP {}", result.status);
            case.status = TestStatus::Fail;
        }
    } else {
        case.status = TestStatus::Blocked;
    }

    case.add_step(TestStep::new(1, "PUT /api/v1/organizations/{id}", "HTTP 200")
        .with_actual("Completed", 0));

    suite.add_case(case);
}

fn test_dept_01_create_department(client: &HttpClient, ctx: &mut TestContext, suite: &mut TestSuite) {
    let mut case = TestCase::new("DEPT-01", "Create Department", "Department Management");
    case.severity = Severity::High;
    case.expected_result = "HTTP 200, department created".to_string();

    let dept_name = format!("Test Dept {}", uuid::Uuid::new_v4().to_string().split('-').next().unwrap());
    let result = client.post("/api/v1/departments", &serde_json::json!({
        "name": &dept_name,
        "code": format!("DEPT_{}", uuid::Uuid::new_v4().to_string().split('-').next().unwrap()),
        "organization_id": ctx.get_resource("organization", "Test Org").or(Some(uuid::Uuid::nil()))
    }), Some(&ctx.access_token)).await;

    if result.status == 200 {
        if let Some(dept_id) = parse_id(&result.body) {
            ctx.store_resource("department", uuid::Uuid::parse_str(&dept_id).unwrap_or(uuid::Uuid::nil()), &dept_name);
            case.actual_result = format!("Department created: {}", dept_id);
            case.status = TestStatus::Pass;
            case.business_logic_verified = true;
        }
    } else {
        case.actual_result = format!("HTTP {} - {:?}", result.status, result.body);
        case.status = TestStatus::Fail;
    }

    case.add_step(TestStep::new(1, "POST /api/v1/departments", "HTTP 200")
        .with_actual(&format!("HTTP {}", result.status), 0));

    suite.add_case(case);
}

fn test_dept_02_list_departments(client: &HttpClient, ctx: &mut TestContext, suite: &mut TestSuite) {
    let mut case = TestCase::new("DEPT-02", "List Departments", "Department Management");
    case.severity = Severity::Medium;
    case.expected_result = "HTTP 200, department list returned".to_string();

    let result = client.get("/api/v1/departments", Some(&ctx.access_token)).await;

    if result.status == 200 {
        case.actual_result = "Departments listed".to_string();
        case.status = TestStatus::Pass;
        case.business_logic_verified = true;
    } else {
        case.actual_result = format!("HTTP {}", result.status);
        case.status = TestStatus::Fail;
    }

    case.add_step(TestStep::new(1, "GET /api/v1/departments", "HTTP 200")
        .with_actual(&format!("HTTP {}", result.status), 0));

    suite.add_case(case);
}

#[derive(Debug, Deserialize)]
struct LoginData {
    access_token: String,
    refresh_token: String,
}

fn parse_login_response(body: &serde_json::Value) -> Result<LoginData, String> {
    let data = body.get("data").ok_or("No data field")?;
    Ok(LoginData {
        access_token: data.get("access_token").and_then(|v| v.as_str()).unwrap_or("").to_string(),
        refresh_token: data.get("refresh_token").and_then(|v| v.as_str()).unwrap_or("").to_string(),
    })
}

fn parse_id(body: &serde_json::Value) -> Option<String> {
    body.get("data")?.get("id")?.as_str().map(|s| s.to_string())
}

fn parse_pagination(body: &serde_json::Value) -> Option<(u64, u64, u64)> {
    let data = body.get("data")?;
    Some((
        data.get("total")?.as_u64()?,
        data.get("page")?.as_u64()?,
        data.get("page_size")?.as_u64()?,
    ))
}