//! HTTP handlers for user account management.
//!
//! These endpoints allow users to manage their account settings:
//! - Change password
//! - Change email
//! - Delete account

use axum::{
    extract::State,
    http::{HeaderMap, StatusCode},
    response::IntoResponse,
    Json,
};
use serde::{Deserialize, Serialize};
use utoipa::ToSchema;

use crate::server::auth::UserOnly;
use crate::server::messages::ApiError;
use crate::server::state::SharedState;

// =============================================================================
// Request/Response Types
// =============================================================================

/// Request to change password.
#[derive(Debug, Deserialize, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct ChangePasswordRequest {
    /// The user's current password for verification
    pub current_password: String,
    /// The new password to set
    pub new_password: String,
}

/// Response after changing password.
#[derive(Debug, Serialize, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct ChangePasswordResponse {
    pub success: bool,
    pub message: String,
}

/// Request to change email.
#[derive(Debug, Deserialize, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct ChangeEmailRequest {
    /// The user's password for verification
    pub password: String,
    /// The new email address to set
    pub new_email: String,
}

/// Response after changing email.
#[derive(Debug, Serialize, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct ChangeEmailResponse {
    pub success: bool,
    pub message: String,
    /// Whether a verification email was sent to the new address
    pub verification_sent: bool,
}

/// Request to delete account.
#[derive(Debug, Deserialize, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct DeleteAccountRequest {
    /// The user's password for verification
    pub password: String,
    /// Confirmation text - must match the user's email
    pub confirmation: String,
}

/// Response after deleting account.
#[derive(Debug, Serialize, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct DeleteAccountResponse {
    pub success: bool,
    pub message: String,
}

// =============================================================================
// Password Validation
// =============================================================================

/// Password strength validation result.
#[derive(Debug)]
pub struct PasswordValidation {
    pub is_valid: bool,
    pub errors: Vec<String>,
}

/// Validate password strength.
/// Requirements:
/// - At least 6 characters (matches login form)
fn validate_password_strength(password: &str) -> PasswordValidation {
    let mut errors = Vec::new();

    if password.len() < 6 {
        errors.push("Password must be at least 6 characters long".to_string());
    }

    PasswordValidation {
        is_valid: errors.is_empty(),
        errors,
    }
}

/// Validate email format.
fn validate_email(email: &str) -> bool {
    // Basic email validation - must contain @ and at least one . after @
    let parts: Vec<&str> = email.split('@').collect();
    if parts.len() != 2 {
        return false;
    }
    let local = parts[0];
    let domain = parts[1];
    // Local part must not be empty
    if local.is_empty() {
        return false;
    }
    // Domain must have at least one dot and not start/end with dot
    domain.contains('.') && !domain.starts_with('.') && !domain.ends_with('.')
}

// =============================================================================
// Supabase Admin Client
// =============================================================================

/// Supabase Admin API client for user management operations.
/// Uses the service role key for admin-level operations.
pub struct SupabaseAdminClient {
    base_url: String,
    secret_api_key: String,
    client: reqwest::Client,
}

impl SupabaseAdminClient {
    /// Create a new Supabase admin client from environment variables.
    pub fn from_env() -> Option<Self> {
        let base_url = std::env::var("SUPABASE_URL").ok()?;
        let secret_api_key = std::env::var("SUPABASE_SECRET_API_KEY").ok()?;

        Some(Self {
            base_url,
            secret_api_key,
            client: reqwest::Client::new(),
        })
    }

    /// Verify a user's password by attempting to sign in.
    pub async fn verify_password(&self, email: &str, password: &str) -> Result<bool, String> {
        let url = format!("{}/auth/v1/token?grant_type=password", self.base_url);

        let response = self
            .client
            .post(&url)
            .header("apikey", &self.secret_api_key)
            .header("Content-Type", "application/json")
            .json(&serde_json::json!({
                "email": email,
                "password": password
            }))
            .send()
            .await
            .map_err(|e| format!("Failed to verify password: {}", e))?;

        Ok(response.status().is_success())
    }

    /// Update a user's password.
    pub async fn update_password(
        &self,
        user_id: &str,
        new_password: &str,
    ) -> Result<(), String> {
        let url = format!("{}/auth/v1/admin/users/{}", self.base_url, user_id);

        let response = self
            .client
            .put(&url)
            .header("apikey", &self.secret_api_key)
            .header("Authorization", format!("Bearer {}", self.secret_api_key))
            .header("Content-Type", "application/json")
            .json(&serde_json::json!({
                "password": new_password
            }))
            .send()
            .await
            .map_err(|e| format!("Failed to update password: {}", e))?;

        if response.status().is_success() {
            Ok(())
        } else {
            let error_text = response.text().await.unwrap_or_default();
            Err(format!("Failed to update password: {}", error_text))
        }
    }

    /// Update a user's email.
    pub async fn update_email(
        &self,
        user_id: &str,
        new_email: &str,
    ) -> Result<(), String> {
        let url = format!("{}/auth/v1/admin/users/{}", self.base_url, user_id);

        let response = self
            .client
            .put(&url)
            .header("apikey", &self.secret_api_key)
            .header("Authorization", format!("Bearer {}", self.secret_api_key))
            .header("Content-Type", "application/json")
            .json(&serde_json::json!({
                "email": new_email,
                "email_confirm": true
            }))
            .send()
            .await
            .map_err(|e| format!("Failed to update email: {}", e))?;

        if response.status().is_success() {
            Ok(())
        } else {
            let error_text = response.text().await.unwrap_or_default();
            Err(format!("Failed to update email: {}", error_text))
        }
    }

    /// Delete a user from Supabase Auth.
    pub async fn delete_user(&self, user_id: &str) -> Result<(), String> {
        let url = format!("{}/auth/v1/admin/users/{}", self.base_url, user_id);

        let response = self
            .client
            .delete(&url)
            .header("apikey", &self.secret_api_key)
            .header("Authorization", format!("Bearer {}", self.secret_api_key))
            .send()
            .await
            .map_err(|e| format!("Failed to delete user: {}", e))?;

        if response.status().is_success() {
            Ok(())
        } else {
            let error_text = response.text().await.unwrap_or_default();
            Err(format!("Failed to delete user: {}", error_text))
        }
    }

    /// Get user info including email.
    pub async fn get_user(&self, user_id: &str) -> Result<Option<String>, String> {
        let url = format!("{}/auth/v1/admin/users/{}", self.base_url, user_id);

        let response = self
            .client
            .get(&url)
            .header("apikey", &self.secret_api_key)
            .header("Authorization", format!("Bearer {}", self.secret_api_key))
            .send()
            .await
            .map_err(|e| format!("Failed to get user: {}", e))?;

        if response.status().is_success() {
            let json: serde_json::Value = response
                .json()
                .await
                .map_err(|e| format!("Failed to parse user data: {}", e))?;
            Ok(json.get("email").and_then(|e| e.as_str()).map(String::from))
        } else if response.status() == reqwest::StatusCode::NOT_FOUND {
            Ok(None)
        } else {
            let error_text = response.text().await.unwrap_or_default();
            Err(format!("Failed to get user: {}", error_text))
        }
    }
}

// =============================================================================
// Supabase User Client (uses user's JWT, no admin required)
// =============================================================================

/// Supabase User API client for self-service operations.
/// Uses the user's JWT token - no admin/service role key required.
pub struct SupabaseUserClient {
    base_url: String,
    anon_key: String,
    jwt_token: String,
    client: reqwest::Client,
}

impl SupabaseUserClient {
    /// Create a new Supabase user client from environment and JWT token.
    pub fn new(jwt_token: String) -> Option<Self> {
        let base_url = std::env::var("SUPABASE_URL").ok()?;
        let anon_key = std::env::var("SUPABASE_ANON_KEY").ok()?;

        Some(Self {
            base_url,
            anon_key,
            jwt_token,
            client: reqwest::Client::new(),
        })
    }

    /// Update the user's password using their own JWT.
    pub async fn update_password(&self, new_password: &str) -> Result<(), String> {
        let url = format!("{}/auth/v1/user", self.base_url);

        let response = self
            .client
            .put(&url)
            .header("apikey", &self.anon_key)
            .header("Authorization", format!("Bearer {}", self.jwt_token))
            .header("Content-Type", "application/json")
            .json(&serde_json::json!({
                "password": new_password
            }))
            .send()
            .await
            .map_err(|e| format!("Failed to update password: {}", e))?;

        if response.status().is_success() {
            Ok(())
        } else {
            let error_text = response.text().await.unwrap_or_default();
            Err(format!("Failed to update password: {}", error_text))
        }
    }

    /// Update the user's email using their own JWT.
    pub async fn update_email(&self, new_email: &str) -> Result<(), String> {
        let url = format!("{}/auth/v1/user", self.base_url);

        let response = self
            .client
            .put(&url)
            .header("apikey", &self.anon_key)
            .header("Authorization", format!("Bearer {}", self.jwt_token))
            .header("Content-Type", "application/json")
            .json(&serde_json::json!({
                "email": new_email
            }))
            .send()
            .await
            .map_err(|e| format!("Failed to update email: {}", e))?;

        if response.status().is_success() {
            Ok(())
        } else {
            let error_text = response.text().await.unwrap_or_default();
            Err(format!("Failed to update email: {}", error_text))
        }
    }

    /// Verify current password by attempting to sign in.
    pub async fn verify_password(&self, email: &str, password: &str) -> Result<bool, String> {
        let url = format!("{}/auth/v1/token?grant_type=password", self.base_url);

        let response = self
            .client
            .post(&url)
            .header("apikey", &self.anon_key)
            .header("Content-Type", "application/json")
            .json(&serde_json::json!({
                "email": email,
                "password": password
            }))
            .send()
            .await
            .map_err(|e| format!("Failed to verify password: {}", e))?;

        Ok(response.status().is_success())
    }
}

// =============================================================================
// Handlers
// =============================================================================

/// Change the authenticated user's password.
///
/// Requires verification of the current password before allowing the change.
/// The new password must meet strength requirements.
#[utoipa::path(
    put,
    path = "/api/v1/users/me/password",
    request_body = ChangePasswordRequest,
    responses(
        (status = 200, description = "Password changed successfully", body = ChangePasswordResponse),
        (status = 400, description = "Invalid request (weak password, wrong current password)", body = ApiError),
        (status = 401, description = "Not authenticated", body = ApiError),
        (status = 403, description = "Forbidden (tool keys not allowed)", body = ApiError),
        (status = 503, description = "Supabase not configured", body = ApiError),
        (status = 500, description = "Internal server error", body = ApiError),
    ),
    security(
        ("bearer_auth" = [])
    ),
    tag = "Users"
)]
pub async fn change_password_handler(
    State(_state): State<SharedState>,
    headers: HeaderMap,
    UserOnly(user): UserOnly,
    Json(req): Json<ChangePasswordRequest>,
) -> impl IntoResponse {
    // Validate new password strength
    let validation = validate_password_strength(&req.new_password);
    if !validation.is_valid {
        return (
            StatusCode::BAD_REQUEST,
            Json(ApiError::new(
                "WEAK_PASSWORD",
                &validation.errors.join("; "),
            )),
        )
            .into_response();
    }

    // Get user's email (required for password verification)
    let email = match &user.email {
        Some(email) => email.clone(),
        None => {
            return (
                StatusCode::BAD_REQUEST,
                Json(ApiError::new("EMAIL_REQUIRED", "User email not available")),
            )
                .into_response();
        }
    };

    // Extract JWT from Authorization header for user-level API calls
    let jwt_token = headers
        .get("Authorization")
        .and_then(|v| v.to_str().ok())
        .and_then(|s| s.strip_prefix("Bearer "))
        .map(|s| s.to_string());

    // Try user client first (uses JWT, no admin required), fall back to admin client
    if let Some(token) = jwt_token {
        if let Some(user_client) = SupabaseUserClient::new(token) {
            // Verify current password
            match user_client.verify_password(&email, &req.current_password).await {
                Ok(true) => {}
                Ok(false) => {
                    return (
                        StatusCode::BAD_REQUEST,
                        Json(ApiError::new("INVALID_PASSWORD", "Current password is incorrect")),
                    )
                        .into_response();
                }
                Err(e) => {
                    tracing::error!("Failed to verify password: {}", e);
                    return (
                        StatusCode::INTERNAL_SERVER_ERROR,
                        Json(ApiError::new("INTERNAL_ERROR", "Failed to verify password")),
                    )
                        .into_response();
                }
            }

            // Update password using user's JWT
            return match user_client.update_password(&req.new_password).await {
                Ok(()) => {
                    tracing::info!("Password changed for user {}", user.user_id);
                    Json(ChangePasswordResponse {
                        success: true,
                        message: "Password changed successfully".to_string(),
                    })
                    .into_response()
                }
                Err(e) => {
                    tracing::error!("Failed to update password: {}", e);
                    (
                        StatusCode::INTERNAL_SERVER_ERROR,
                        Json(ApiError::new("INTERNAL_ERROR", "Failed to update password")),
                    )
                        .into_response()
                }
            };
        }
    }

    // Fall back to admin client if user client not available
    let admin_client = match SupabaseAdminClient::from_env() {
        Some(client) => client,
        None => {
            return (
                StatusCode::SERVICE_UNAVAILABLE,
                Json(ApiError::new(
                    "SUPABASE_NOT_CONFIGURED",
                    "Supabase not configured. Ensure SUPABASE_URL and SUPABASE_ANON_KEY are set.",
                )),
            )
                .into_response();
        }
    };

    // Verify current password
    match admin_client.verify_password(&email, &req.current_password).await {
        Ok(true) => {}
        Ok(false) => {
            return (
                StatusCode::BAD_REQUEST,
                Json(ApiError::new("INVALID_PASSWORD", "Current password is incorrect")),
            )
                .into_response();
        }
        Err(e) => {
            tracing::error!("Failed to verify password: {}", e);
            return (
                StatusCode::INTERNAL_SERVER_ERROR,
                Json(ApiError::new("INTERNAL_ERROR", "Failed to verify password")),
            )
                .into_response();
        }
    }

    // Update password in Supabase
    match admin_client
        .update_password(&user.user_id.to_string(), &req.new_password)
        .await
    {
        Ok(()) => {
            tracing::info!("Password changed for user {}", user.user_id);
            Json(ChangePasswordResponse {
                success: true,
                message: "Password changed successfully".to_string(),
            })
            .into_response()
        }
        Err(e) => {
            tracing::error!("Failed to update password: {}", e);
            (
                StatusCode::INTERNAL_SERVER_ERROR,
                Json(ApiError::new("INTERNAL_ERROR", "Failed to update password")),
            )
                .into_response()
        }
    }
}

/// Change the authenticated user's email address.
///
/// Requires password verification before allowing the change.
/// The new email will be updated directly (Supabase handles verification if configured).
#[utoipa::path(
    put,
    path = "/api/v1/users/me/email",
    request_body = ChangeEmailRequest,
    responses(
        (status = 200, description = "Email changed successfully", body = ChangeEmailResponse),
        (status = 400, description = "Invalid request (invalid email, wrong password)", body = ApiError),
        (status = 401, description = "Not authenticated", body = ApiError),
        (status = 403, description = "Forbidden (tool keys not allowed)", body = ApiError),
        (status = 503, description = "Supabase not configured", body = ApiError),
        (status = 500, description = "Internal server error", body = ApiError),
    ),
    security(
        ("bearer_auth" = [])
    ),
    tag = "Users"
)]
pub async fn change_email_handler(
    State(state): State<SharedState>,
    headers: HeaderMap,
    UserOnly(user): UserOnly,
    Json(req): Json<ChangeEmailRequest>,
) -> impl IntoResponse {
    let Some(ref pool) = state.db_pool else {
        return (
            StatusCode::SERVICE_UNAVAILABLE,
            Json(ApiError::new("DB_UNAVAILABLE", "Database not configured")),
        )
            .into_response();
    };

    // Validate new email format
    if !validate_email(&req.new_email) {
        return (
            StatusCode::BAD_REQUEST,
            Json(ApiError::new("INVALID_EMAIL", "Invalid email format")),
        )
            .into_response();
    }

    // Get user's current email (required for password verification)
    let current_email = match &user.email {
        Some(email) => email.clone(),
        None => {
            return (
                StatusCode::BAD_REQUEST,
                Json(ApiError::new("EMAIL_REQUIRED", "User email not available")),
            )
                .into_response();
        }
    };

    // Extract JWT from Authorization header for user-level API calls
    let jwt_token = headers
        .get("Authorization")
        .and_then(|v| v.to_str().ok())
        .and_then(|s| s.strip_prefix("Bearer "))
        .map(|s| s.to_string());

    // Try user client first (uses JWT, no admin required), fall back to admin client
    if let Some(token) = jwt_token {
        if let Some(user_client) = SupabaseUserClient::new(token) {
            // Verify password
            match user_client.verify_password(&current_email, &req.password).await {
                Ok(true) => {}
                Ok(false) => {
                    return (
                        StatusCode::BAD_REQUEST,
                        Json(ApiError::new("INVALID_PASSWORD", "Password is incorrect")),
                    )
                        .into_response();
                }
                Err(e) => {
                    tracing::error!("Failed to verify password: {}", e);
                    return (
                        StatusCode::INTERNAL_SERVER_ERROR,
                        Json(ApiError::new("INTERNAL_ERROR", "Failed to verify password")),
                    )
                        .into_response();
                }
            }

            // Update email using user's JWT
            if let Err(e) = user_client.update_email(&req.new_email).await {
                tracing::error!("Failed to update email in Supabase: {}", e);
                return (
                    StatusCode::INTERNAL_SERVER_ERROR,
                    Json(ApiError::new("INTERNAL_ERROR", "Failed to update email")),
                )
                    .into_response();
            }

            // Update email in our database
            if let Err(e) = sqlx::query("UPDATE users SET email = $1, updated_at = NOW() WHERE id = $2")
                .bind(&req.new_email)
                .bind(user.user_id)
                .execute(pool)
                .await
            {
                tracing::error!("Failed to update email in database: {}", e);
            }

            tracing::info!(
                "Email changed for user {} from {} to {}",
                user.user_id,
                current_email,
                req.new_email
            );

            return Json(ChangeEmailResponse {
                success: true,
                message: "Email changed successfully".to_string(),
                verification_sent: false,
            })
            .into_response();
        }
    }

    // Fall back to admin client if user client not available
    let admin_client = match SupabaseAdminClient::from_env() {
        Some(client) => client,
        None => {
            return (
                StatusCode::SERVICE_UNAVAILABLE,
                Json(ApiError::new(
                    "SUPABASE_NOT_CONFIGURED",
                    "Supabase not configured. Ensure SUPABASE_URL and SUPABASE_ANON_KEY are set.",
                )),
            )
                .into_response();
        }
    };

    // Verify password
    match admin_client.verify_password(&current_email, &req.password).await {
        Ok(true) => {}
        Ok(false) => {
            return (
                StatusCode::BAD_REQUEST,
                Json(ApiError::new("INVALID_PASSWORD", "Password is incorrect")),
            )
                .into_response();
        }
        Err(e) => {
            tracing::error!("Failed to verify password: {}", e);
            return (
                StatusCode::INTERNAL_SERVER_ERROR,
                Json(ApiError::new("INTERNAL_ERROR", "Failed to verify password")),
            )
                .into_response();
        }
    }

    // Update email in Supabase
    if let Err(e) = admin_client
        .update_email(&user.user_id.to_string(), &req.new_email)
        .await
    {
        tracing::error!("Failed to update email in Supabase: {}", e);
        return (
            StatusCode::INTERNAL_SERVER_ERROR,
            Json(ApiError::new("INTERNAL_ERROR", "Failed to update email")),
        )
            .into_response();
    }

    // Update email in our database
    if let Err(e) = sqlx::query("UPDATE users SET email = $1, updated_at = NOW() WHERE id = $2")
        .bind(&req.new_email)
        .bind(user.user_id)
        .execute(pool)
        .await
    {
        tracing::error!("Failed to update email in database: {}", e);
    }

    tracing::info!(
        "Email changed for user {} from {} to {}",
        user.user_id,
        current_email,
        req.new_email
    );

    Json(ChangeEmailResponse {
        success: true,
        message: "Email changed successfully".to_string(),
        verification_sent: false,
    })
    .into_response()
}

/// Delete the authenticated user's account.
///
/// This permanently deletes:
/// - The user's Supabase Auth account
/// - The user's record in our database
/// - All associated data (API keys, files, tasks, etc. via CASCADE)
///
/// Requires password verification and confirmation text matching the user's email.
#[utoipa::path(
    delete,
    path = "/api/v1/users/me",
    request_body = DeleteAccountRequest,
    responses(
        (status = 200, description = "Account deleted successfully", body = DeleteAccountResponse),
        (status = 400, description = "Invalid request (wrong password, wrong confirmation)", body = ApiError),
        (status = 401, description = "Not authenticated", body = ApiError),
        (status = 403, description = "Forbidden (tool keys not allowed)", body = ApiError),
        (status = 503, description = "Supabase not configured", body = ApiError),
        (status = 500, description = "Internal server error", body = ApiError),
    ),
    security(
        ("bearer_auth" = [])
    ),
    tag = "Users"
)]
pub async fn delete_account_handler(
    State(state): State<SharedState>,
    UserOnly(user): UserOnly,
    Json(req): Json<DeleteAccountRequest>,
) -> impl IntoResponse {
    let Some(ref pool) = state.db_pool else {
        return (
            StatusCode::SERVICE_UNAVAILABLE,
            Json(ApiError::new("DB_UNAVAILABLE", "Database not configured")),
        )
            .into_response();
    };

    // Get Supabase admin client - required for full account deletion
    let admin_client = match SupabaseAdminClient::from_env() {
        Some(client) => client,
        None => {
            return (
                StatusCode::SERVICE_UNAVAILABLE,
                Json(ApiError::new(
                    "SUPABASE_ADMIN_NOT_CONFIGURED",
                    "Account deletion requires SUPABASE_SECRET_API_KEY to be configured",
                )),
            )
                .into_response();
        }
    };

    // Verify confirmation is "DELETE MY ACCOUNT"
    const REQUIRED_CONFIRMATION: &str = "DELETE MY ACCOUNT";
    if req.confirmation != REQUIRED_CONFIRMATION {
        return (
            StatusCode::BAD_REQUEST,
            Json(ApiError::new(
                "INVALID_CONFIRMATION",
                format!("Confirmation text must be exactly: {}", REQUIRED_CONFIRMATION),
            )),
        )
            .into_response();
    }

    // Get user's email (required for password verification)
    let email = match &user.email {
        Some(e) => e.clone(),
        None => {
            return (
                StatusCode::BAD_REQUEST,
                Json(ApiError::new("EMAIL_REQUIRED", "User email not available")),
            )
                .into_response();
        }
    };

    // Verify password
    match admin_client.verify_password(&email, &req.password).await {
        Ok(true) => {}
        Ok(false) => {
            return (
                StatusCode::BAD_REQUEST,
                Json(ApiError::new("INVALID_PASSWORD", "Password is incorrect")),
            )
                .into_response();
        }
        Err(e) => {
            tracing::error!("Failed to verify password: {}", e);
            return (
                StatusCode::INTERNAL_SERVER_ERROR,
                Json(ApiError::new("INTERNAL_ERROR", "Failed to verify password")),
            )
                .into_response();
        }
    }

    // Delete from our database first (this will cascade to related records)
    // Get the owner_id before deleting
    let owner_id = user.owner_id;

    // Delete API keys for this user (explicit deletion for audit purposes)
    if let Err(e) = sqlx::query("UPDATE api_keys SET revoked_at = NOW() WHERE user_id = $1 AND revoked_at IS NULL")
        .bind(user.user_id)
        .execute(pool)
        .await
    {
        tracing::warn!("Failed to revoke API keys during account deletion: {}", e);
    }

    // Delete user record
    if let Err(e) = sqlx::query("DELETE FROM users WHERE id = $1")
        .bind(user.user_id)
        .execute(pool)
        .await
    {
        tracing::error!("Failed to delete user from database: {}", e);
        return (
            StatusCode::INTERNAL_SERVER_ERROR,
            Json(ApiError::new("INTERNAL_ERROR", "Failed to delete account")),
        )
            .into_response();
    }

    // Delete files owned by this user
    if let Err(e) = sqlx::query("DELETE FROM files WHERE owner_id = $1")
        .bind(owner_id)
        .execute(pool)
        .await
    {
        tracing::warn!("Failed to delete user files: {}", e);
    }

    // Delete tasks owned by this user
    if let Err(e) = sqlx::query("DELETE FROM tasks WHERE owner_id = $1")
        .bind(owner_id)
        .execute(pool)
        .await
    {
        tracing::warn!("Failed to delete user tasks: {}", e);
    }

    // Delete mesh chat conversations owned by this user
    if let Err(e) = sqlx::query("DELETE FROM mesh_chat_conversations WHERE owner_id = $1")
        .bind(owner_id)
        .execute(pool)
        .await
    {
        tracing::warn!("Failed to delete mesh chat conversations: {}", e);
    }

    // Delete daemons owned by this user
    if let Err(e) = sqlx::query("DELETE FROM daemons WHERE owner_id = $1")
        .bind(owner_id)
        .execute(pool)
        .await
    {
        tracing::warn!("Failed to delete user daemons: {}", e);
    }

    // Delete owner record
    if let Err(e) = sqlx::query("DELETE FROM owners WHERE id = $1")
        .bind(owner_id)
        .execute(pool)
        .await
    {
        tracing::warn!("Failed to delete owner record: {}", e);
    }

    // Delete from Supabase Auth
    if let Err(e) = admin_client.delete_user(&user.user_id.to_string()).await {
        tracing::error!("Failed to delete user from Supabase Auth: {}", e);
        return (
            StatusCode::INTERNAL_SERVER_ERROR,
            Json(ApiError::new(
                "SUPABASE_DELETE_FAILED",
                "Failed to delete user from authentication system",
            )),
        )
            .into_response();
    }

    tracing::info!("Account deleted for user {} ({})", user.user_id, email);

    Json(DeleteAccountResponse {
        success: true,
        message: "Account deleted successfully".to_string(),
    })
    .into_response()
}

// =============================================================================
// Tests
// =============================================================================

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

    #[test]
    fn test_password_validation_success() {
        // Minimum 6 characters
        let result = validate_password_strength("abcdef");
        assert!(result.is_valid);
        assert!(result.errors.is_empty());

        let result = validate_password_strength("Password123");
        assert!(result.is_valid);
        assert!(result.errors.is_empty());
    }

    #[test]
    fn test_password_validation_too_short() {
        let result = validate_password_strength("12345");
        assert!(!result.is_valid);
        assert!(result.errors.iter().any(|e| e.contains("6 characters")));
    }

    #[test]
    fn test_email_validation_valid() {
        assert!(validate_email("user@example.com"));
        assert!(validate_email("user.name@example.co.uk"));
        assert!(validate_email("user+tag@example.org"));
    }

    #[test]
    fn test_email_validation_invalid() {
        assert!(!validate_email("userexample.com"));
        assert!(!validate_email("user@"));
        assert!(!validate_email("@example.com"));
        assert!(!validate_email("user@.com"));
        assert!(!validate_email("user@example."));
    }
}
