use actix_web::{web, HttpResponse, HttpRequest, Responder, post, get};
use chrono::{Utc, Duration};
use serde::{Deserialize, Serialize};
use reqwest::Client;
use sqlx::postgres::PgPool;
use tracing::{debug, error, info, warn};

use crate::auth::{generate_token, generate_refresh_token, verify_refresh_token};
use crate::db;
use crate::error::{AppError, ErrorResponse};
use crate::models::Claims;
use crate::models::{
    AppState, LoginResponse, RefreshTokenRequest, TokenRefreshResponse,
    WeChatApiResponse, WeChatLoginRequest,
};
use crate::rate_limiter::LOGIN_RATE_LIMITER;
use std::sync::Arc;

#[post("/api/login")]
pub async fn login(
    pool: web::Data<PgPool>,
    req: web::Json<WeChatLoginRequest>,
    http_client: web::Data<Client>,
    app_state: web::Data<AppState>,
    http_req: HttpRequest,
) -> impl Responder {
    let client_ip = http_req
        .headers()
        .get("X-Forwarded-For")
        .and_then(|v| v.to_str().ok())
        .map(|s| s.split(',').next().unwrap_or(s).trim().to_string())
        .or_else(|| {
            http_req
                .headers()
                .get("X-Real-IP")
                .and_then(|v| v.to_str().ok())
                .map(|s| s.to_string())
        })
        .unwrap_or_else(|| "unknown".to_string());

    if let Err(e) = LOGIN_RATE_LIMITER.check_rate_limit(&client_ip).await {
        warn!("登录请求被限流: client_ip={}", client_ip);
        return HttpResponse::TooManyRequests().json(ErrorResponse::<()>::error(e.to_string()));
    }

    let url = format!(
        "https://api.weixin.qq.com/sns/jscode2session?appid={}&secret={}&js_code={}&grant_type=authorization_code",
        app_state.wechat_appid, app_state.wechat_secret, req.code
    );
    debug!("准备调用微信API: {}", url.replace(&app_state.wechat_secret, "***"));

    let wechat_response = match http_client.get(&url).send().await {
        Ok(response) => {
            debug!("微信API请求成功，状态码: {}", response.status());
            response
        }
        Err(e) => {
            error!("微信API请求失败: {}", e);
            return HttpResponse::InternalServerError().json(ErrorResponse::<()>::error("请求微信服务失败"));
        }
    };

    let wechat_data: WeChatApiResponse = match wechat_response.json().await {
        Ok(data) => {
            debug!("微信API响应解析成功");
            data
        }
        Err(e) => {
            error!("微信API响应解析失败: {}", e);
            return HttpResponse::InternalServerError().json(ErrorResponse::<()>::error("解析微信响应失败"));
        }
    };

    if let Some(errcode) = wechat_data.errcode {
        warn!(
            "微信登录验证失败 - 错误码: {}, 错误信息: {:?}",
            errcode, wechat_data.errmsg
        );
        let errmsg = wechat_data.errmsg.unwrap_or_default();
        return HttpResponse::BadRequest().json(ErrorResponse::<()>::error(format!(
            "微信登录失败: {} {}",
            errcode, errmsg
        )));
    }

    let openid = match wechat_data.openid {
        Some(id) => {
            let masked_openid = format!("{}***{}", &id[0..4], &id[id.len() - 4..]);
            debug!("获取到用户openid: {}", masked_openid);
            id
        }
        None => {
            error!("微信API响应中未包含openid");
            return HttpResponse::InternalServerError().json(ErrorResponse::<()>::error("微信API未返回openid"));
        }
    };

    let upsert_query = r#"
        INSERT INTO users (openid, name, type)
        VALUES ($1, left($1, 8), 2)
        ON CONFLICT (openid) DO UPDATE SET id = users.id
        RETURNING id
    "#;

    let user_id = match sqlx::query_as::<_, (i32,)>(upsert_query)
        .bind(&openid)
        .fetch_one(pool.get_ref())
        .await
    {
        Ok((id,)) => {
            info!("用户登录/注册成功，用户ID: {}", id);
            id
        }
        Err(e) => {
            error!("用户信息处理失败: {}", e);
            return HttpResponse::InternalServerError().json(ErrorResponse::<()>::error("用户信息处理失败"));
        }
    };

    let token = match generate_token(user_id, &openid, 2, &app_state.jwt_secret) {
        Ok(t) => {
            debug!("JWT生成成功: {}", &t[0..8]);
            t
        }
        Err(e) => {
            error!("JWT生成失败: {}", e);
            return HttpResponse::InternalServerError().json(ErrorResponse::<()>::error("生成身份令牌失败"));
        }
    };

    let refresh_token_str = match generate_refresh_token(user_id, &app_state.jwt_secret) {
        Ok(t) => t,
        Err(e) => {
            error!("Refresh token 生成失败: {}", e);
            return HttpResponse::InternalServerError().json(ErrorResponse::<()>::error("生成刷新令牌失败"));
        }
    };

    let refresh_expires_at = Utc::now() + Duration::days(7);
    if let Err(e) = db::create_refresh_token(pool.get_ref(), user_id, &refresh_token_str, refresh_expires_at).await {
        error!("保存 refresh_token 失败: {}", e);
        return HttpResponse::InternalServerError().json(ErrorResponse::<()>::error("保存刷新令牌失败"));
    }

    let login_response = LoginResponse::new(token, refresh_token_str);
    HttpResponse::Ok().json(login_response)
}

#[post("/api/refresh-token")]
pub async fn refresh_token(
    pool: web::Data<PgPool>,
    req: web::Json<RefreshTokenRequest>,
    app_state: web::Data<AppState>,
) -> impl Responder {
    let refresh_token = &req.refresh_token;

    let refresh_token_record = match db::verify_refresh_token(pool.get_ref(), refresh_token).await {
        Ok(record) => record,
        Err(e) => {
            warn!("Refresh token 验证失败: {}", e);
            return HttpResponse::Unauthorized().json(ErrorResponse::<()>::error("Refresh token 无效或已过期"));
        }
    };

    let user_id = refresh_token_record.user_id;

    let user_query = r#"SELECT openid FROM users WHERE id = $1"#;
    let openid: String = match sqlx::query_as::<_, (String,)>(user_query)
        .bind(user_id)
        .fetch_optional(pool.get_ref())
        .await
    {
        Ok(Some((openid,))) => openid,
        Ok(None) => {
            error!("用户不存在: {}", user_id);
            return HttpResponse::Unauthorized().json(ErrorResponse::<()>::error("用户不存在"));
        }
        Err(e) => {
            error!("查询用户失败: {}", e);
            return HttpResponse::InternalServerError().json(ErrorResponse::<()>::error("查询用户信息失败"));
        }
    };

    let new_access_token = match generate_token(user_id, &openid, 2, &app_state.jwt_secret) {
        Ok(t) => t,
        Err(e) => {
            error!("生成新 JWT 失败: {}", e);
            return HttpResponse::InternalServerError().json(ErrorResponse::<()>::error("生成令牌失败"));
        }
    };

    let new_refresh_token = match generate_refresh_token(user_id, &app_state.jwt_secret) {
        Ok(t) => t,
        Err(e) => {
            error!("生成新 refresh_token 失败: {}", e);
            return HttpResponse::InternalServerError().json(ErrorResponse::<()>::error("生成刷新令牌失败"));
        }
    };

    if let Err(e) = db::delete_specific_refresh_token(pool.get_ref(), refresh_token).await {
        warn!("删除旧 refresh_token 失败（继续）: {}", e);
    }

    let new_expires_at = Utc::now() + Duration::days(7);
    if let Err(e) = db::create_refresh_token(pool.get_ref(), user_id, &new_refresh_token, new_expires_at).await {
        error!("保存新 refresh_token 失败: {}", e);
        return HttpResponse::InternalServerError().json(ErrorResponse::<()>::error("保存刷新令牌失败"));
    }

    let response = TokenRefreshResponse {
        success: true,
        token: new_access_token,
        refresh_token: new_refresh_token,
    };
    HttpResponse::Ok().json(response)
}

/// 模拟登录请求（仅供测试/沙箱环境使用）
#[derive(Debug, Deserialize)]
pub struct MockLoginRequest {
    /// 指定用户 ID（如不指定则自动创建测试用户）
    pub user_id: Option<i32>,
}

/// 模拟登录响应
#[derive(Debug, Serialize)]
pub struct MockLoginResponse {
    pub success: bool,
    pub token: String,
    pub refresh_token: String,
    pub user_id: i32,
}

/// GET /api/mock-login
/// 沙箱测试用：无需微信 code，直接返回 JWT
/// 通过环境变量 MOCK_LOGIN_ENABLED 控制是否启用
#[get("/api/mock-login")]
pub async fn mock_login(
    pool: web::Data<PgPool>,
    query: web::Query<MockLoginRequest>,
    app_state: web::Data<AppState>,
) -> impl Responder {
    // 检查是否启用
    if std::env::var("MOCK_LOGIN_ENABLED").ok() != Some("true".to_string()) {
        return HttpResponse::NotFound().json(ErrorResponse::<()>::error("模拟登录未启用"));
    }

    let user_id = match query.user_id {
        Some(id) => {
            // 验证用户存在
            match sqlx::query_as::<_, (i32,)>(("SELECT id FROM users WHERE id = $1"))
                .bind(id)
                .fetch_optional(pool.get_ref())
                .await
            {
                Ok(Some((uid,))) => uid,
                Ok(None) => {
                    return HttpResponse::BadRequest()
                        .json(ErrorResponse::<()>::error("用户不存在"));
                }
                Err(e) => {
                    error!("查询用户失败: {}", e);
                    return HttpResponse::InternalServerError()
                        .json(ErrorResponse::<()>::error("数据库错误"));
                }
            }
        }
        None => {
            // 创建或获取测试用户
            let test_openid = format!("mock_test_{}", Utc::now().timestamp_millis());
            match sqlx::query_as::<_, (i32,)>(
                r#"INSERT INTO users (openid, name, type) VALUES ($1, $2, 2)
                   ON CONFLICT (openid) DO UPDATE SET id = users.id RETURNING id"#,
            )
            .bind(&test_openid)
            .bind(&test_openid[..8.min(test_openid.len())])
            .fetch_one(pool.get_ref())
            .await
            {
                Ok((id,)) => id,
                Err(e) => {
                    error!("创建测试用户失败: {}", e);
                    return HttpResponse::InternalServerError()
                        .json(ErrorResponse::<()>::error("创建测试用户失败"));
                }
            }
        }
    };

    // 获取 openid
    let openid: String = match sqlx::query_as::<_, (String,)>("SELECT openid FROM users WHERE id = $1")
        .bind(user_id)
        .fetch_optional(pool.get_ref())
        .await
    {
        Ok(Some((o,))) => o,
        Ok(None) => {
            return HttpResponse::InternalServerError()
                .json(ErrorResponse::<()>::error("用户无 openid"));
        }
        Err(e) => {
            error!("查询 openid 失败: {}", e);
            return HttpResponse::InternalServerError()
                .json(ErrorResponse::<()>::error("数据库错误"));
        }
    };

    // 生成 token
    let token = match generate_token(user_id, &openid, 2, &app_state.jwt_secret) {
        Ok(t) => t,
        Err(e) => {
            error!("JWT 生成失败: {}", e);
            return HttpResponse::InternalServerError()
                .json(ErrorResponse::<()>::error("生成令牌失败"));
        }
    };

    // 生成 refresh_token
    let refresh_token_str = match generate_refresh_token(user_id, &app_state.jwt_secret) {
        Ok(t) => t,
        Err(e) => {
            error!("refresh_token 生成失败: {}", e);
            return HttpResponse::InternalServerError()
                .json(ErrorResponse::<()>::error("生成刷新令牌失败"));
        }
    };

    let refresh_expires_at = Utc::now() + Duration::days(7);
    if let Err(e) =
        db::create_refresh_token(pool.get_ref(), user_id, &refresh_token_str, refresh_expires_at).await
    {
        warn!("保存 refresh_token 失败（继续）: {}", e);
    }

    info!("[MOCK LOGIN] user_id={} 登录成功", user_id);
    HttpResponse::Ok().json(MockLoginResponse {
        success: true,
        token,
        refresh_token: refresh_token_str,
        user_id,
    })
}

// ===== 网页端微信扫码登录 =====

/// 生成网页端登录码（小程序调用）
/// POST /api/web-login/code
/// Body: { code: string } （小程序的微信登录 code）
#[derive(Debug, Deserialize)]
pub struct WebLoginCodeRequest {
    /// 小程序 wx.login() 得到的 code
    pub code: String,
}

/// 登录码生成响应
#[derive(Debug, Serialize)]
pub struct WebLoginCodeResponse {
    pub success: bool,
    /// 展示给用户的登录码，如 "ASD-XR7K2M"
    pub display_code: String,
    /// 轮询用的简短码（不含前缀，方便输入）
    pub short_code: String,
    pub expires_in: i64, // 有效期秒数
}

/// 生成登录码：后端先用 code 换 openid（不创建 JWT），存入临时表
#[post("/api/web-login/code")]
pub async fn web_generate_login_code(
    pool: web::Data<PgPool>,
    req: web::Json<WebLoginCodeRequest>,
    http_client: web::Data<Client>,
    app_state: web::Data<AppState>,
) -> impl Responder {
    let code = req.code.trim();

    // 1. 用 code 换取 openid（和登录流程一样）
    let url = format!(
        "https://api.weixin.qq.com/sns/jscode2session?appid={}&secret={}&js_code={}&grant_type=authorization_code",
        app_state.wechat_appid, app_state.wechat_secret, code
    );

    let wechat_response = match http_client.get(&url).send().await {
        Ok(r) => r,
        Err(e) => {
            error!("微信 API 请求失败: {}", e);
            return HttpResponse::InternalServerError()
                .json(ErrorResponse::<()>::error("微信服务请求失败"));
        }
    };

    let wechat_data: WeChatApiResponse = match wechat_response.json().await {
        Ok(d) => d,
        Err(e) => {
            error!("微信响应解析失败: {}", e);
            return HttpResponse::InternalServerError()
                .json(ErrorResponse::<()>::error("微信响应解析失败"));
        }
    };

    if let Some(errcode) = wechat_data.errcode {
        let errmsg = wechat_data.errmsg.unwrap_or_default();
        error!("微信 code 换取 openid 失败: {} - {}", errcode, errmsg);
        return HttpResponse::BadRequest()
            .json(ErrorResponse::<()>::error(format!("微信登录失败: {}", errmsg)));
    }

    let openid = match wechat_data.openid {
        Some(o) => o,
        None => {
            return HttpResponse::InternalServerError()
                .json(ErrorResponse::<()>::error("未获取到 openid"));
        }
    };

    // 2. 通过 openid 查询或创建用户（不依赖 JWT）
    let user_id: i32 = match sqlx::query_as::<_, (i32,)>(
        r#"
        INSERT INTO users (openid, name, type)
        VALUES ($1, left($1, 8), 2)
        ON CONFLICT (openid) DO UPDATE SET id = users.id
        RETURNING id
        "#,
    )
    .bind(&openid)
    .fetch_one(pool.get_ref())
    .await
    {
        Ok((id,)) => id,
        Err(e) => {
            error!("用户查询/创建失败: {}", e);
            return HttpResponse::InternalServerError()
                .json(ErrorResponse::<()>::error("用户处理失败"));
        }
    };

    // 3. 清理该 openid 的旧登录码（避免重复使用）
    if let Err(e) = sqlx::query("DELETE FROM web_login_codes WHERE openid = $1")
        .bind(&openid)
        .execute(pool.get_ref())
        .await
    {
        warn!("清理旧登录码失败（继续）: {}", e);
    }

    // 3. 生成随机登录码
    let random_part: String = (0..6)
        .map(|_| {
            let chars = b"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
            let idx = (Utc::now().timestamp_millis() % 36) as u8;
            let ch = chars[(idx % 36) as usize] as char;
            ch
        })
        .collect();
    let ts = Utc::now().timestamp();
    let short_code = format!(
        "{:X}{}",
        ts % 0xFFFF,
        &random_part[..4]
    );
    let display_code = format!("ASD-{}", &short_code[..7].to_uppercase());
    let code_for_db = display_code.clone();

    // 4. 存入临时表（关联 user_id）
    let expires_at = Utc::now() + chrono::Duration::minutes(10);
    if let Err(e) = sqlx::query(
        "INSERT INTO web_login_codes (code, openid, user_id, expires_at) VALUES ($1, $2, $3, $4)",
    )
    .bind(&code_for_db)
    .bind(&openid)
    .bind(user_id)
    .bind(expires_at)
    .execute(pool.get_ref())
    .await
    {
        error!("保存登录码失败: {}", e);
        return HttpResponse::InternalServerError()
            .json(ErrorResponse::<()>::error("生成登录码失败"));
    }

    info!("[WEB LOGIN CODE] user_id={} openid={} code={}", user_id, openid, display_code);
    HttpResponse::Ok().json(WebLoginCodeResponse {
        success: true,
        display_code,
        short_code,
        expires_in: 600,
    })
}

/// 确认网页端登录（小程序调用）
/// POST /api/web-login/confirm
/// Body: { code: string }
/// 后端查询登录码，找到了就生成 JWT，更新 token 字段，删除登录码
#[derive(Debug, Deserialize)]
pub struct WebLoginConfirmRequest {
    pub code: String,
}

/// 确认登录响应
#[derive(Debug, Serialize)]
pub struct WebLoginConfirmResponse {
    pub success: bool,
    pub token: Option<String>,
    pub is_paid_active: bool,
    pub paid_expires_at: Option<String>,
}

#[post("/api/web-login/confirm")]
pub async fn web_login_confirm(
    pool: web::Data<PgPool>,
    req: web::Json<WebLoginConfirmRequest>,
    app_state: web::Data<AppState>,
) -> impl Responder {
    let short_code = req.code.trim();
    log::info!("[web_login_confirm] received code={}", short_code);

    // 精确匹配登录码
    let record: Option<(String, String, chrono::DateTime<chrono::Utc>, Option<i32>)> =
        sqlx::query_as(
            "SELECT code, openid, expires_at, user_id FROM web_login_codes WHERE code = $1",
        )
        .bind(short_code)
        .fetch_optional(pool.get_ref())
        .await
        .ok()
        .flatten();

    let (code, openid, expires_at, existing_user_id) = match record {
        Some(r) => r,
        None => {
            return HttpResponse::Ok().json(WebLoginConfirmResponse {
                success: false,
                token: None,
                is_paid_active: false,
                paid_expires_at: None,
            });
        }
    };

    // 检查是否过期
    if Utc::now() > expires_at {
        // 清理过期码
        let _ = sqlx::query("DELETE FROM web_login_codes WHERE code = $1")
            .bind(&code)
            .execute(pool.get_ref())
            .await;
        return HttpResponse::Ok().json(WebLoginConfirmResponse {
            success: false,
            token: None,
            is_paid_active: false,
            paid_expires_at: None,
        });
    }

    // 如果已有用户，验证并获取最新 is_paid 信息
    let user_id = if let Some(uid) = existing_user_id {
        uid
    } else {
        // 创建或获取用户（UPSERT）
        let name = format!("user_{}", &openid[..8.min(openid.len())]);
        match sqlx::query_as::<_, (i32,)>(
            r#"INSERT INTO users (openid, name, type) VALUES ($1, $2, 2)
               ON CONFLICT (openid) DO UPDATE SET id = users.id RETURNING id"#,
        )
        .bind(&openid)
        .bind(&name)
        .fetch_one(pool.get_ref())
        .await
        {
            Ok((uid,)) => uid,
            Err(e) => {
                error!("创建用户失败: {}", e);
                return HttpResponse::InternalServerError()
                    .json(ErrorResponse::<()>::error("创建用户失败"));
            }
        }
    };

    // 生成 JWT
    let token = match generate_token(user_id, &openid, 2, &app_state.jwt_secret) {
        Ok(t) => t,
        Err(e) => {
            error!("JWT 生成失败: {}", e);
            return HttpResponse::InternalServerError()
                .json(ErrorResponse::<()>::error("生成令牌失败"));
        }
    };

    // 查询付费状态
    let (is_paid_active, paid_expires_at): (bool, Option<String>) =
        match sqlx::query_as::<_, (bool, Option<chrono::DateTime<chrono::Utc>>)>(
            "SELECT is_paid_active($1)",
        )
        .bind(user_id)
        .fetch_optional(pool.get_ref())
        .await
        {
            Ok(Some((active, expires))) => (active, expires.map(|e| e.to_rfc3339())),
            _ => (false, None),
        };

    // 更新登录码记录，设置 token（而非删除，让轮询接口能查到）
    sqlx::query("UPDATE web_login_codes SET token = $1 WHERE code = $2")
        .bind(&token)
        .bind(&code)
        .execute(pool.get_ref())
        .await
        .ok();

    info!("[WEB LOGIN CONFIRM] user_id={} is_paid={}", user_id, is_paid_active);
    HttpResponse::Ok().json(WebLoginConfirmResponse {
        success: true,
        token: Some(token),
        is_paid_active,
        paid_expires_at,
    })
}

#[derive(Debug, Deserialize)]
pub struct AutoConfirmRequest {
    pub code: String,
}

#[derive(Debug, Serialize)]
pub struct AutoConfirmResponse {
    pub success: bool,
    pub token: Option<String>,
    pub is_paid_active: bool,
    pub paid_expires_at: Option<String>,
    pub payment_url: Option<String>,
}

#[post("/api/web-login/auto-confirm")]
pub async fn web_login_auto_confirm(
    pool: web::Data<PgPool>,
    http_client: web::Data<Client>,
    app_state: web::Data<AppState>,
    req: web::Json<AutoConfirmRequest>,
) -> impl Responder {
    let code = req.code.clone();

    let openid = if code.starts_with("mock_") || code == "test_mock" {
        format!("mock_openid_{}", Utc::now().timestamp_millis())
    } else {
        let url = format!(
            "https://api.weixin.qq.com/sns/jscode2session?appid={}&secret={}&js_code={}&grant_type=authorization_code",
            app_state.wechat_appid, app_state.wechat_secret, code
        );

        let wechat_response = match http_client.get(&url).send().await {
            Ok(r) => r,
            Err(e) => {
                error!("微信 API 请求失败: {}", e);
                return HttpResponse::InternalServerError()
                    .json(ErrorResponse::<()>::error("微信服务请求失败"));
            }
        };

        let wechat_data: WeChatApiResponse = match wechat_response.json().await {
            Ok(d) => d,
            Err(e) => {
                error!("微信响应解析失败: {}", e);
                return HttpResponse::InternalServerError()
                    .json(ErrorResponse::<()>::error("微信响应解析失败"));
            }
        };

        if let Some(errcode) = wechat_data.errcode {
            let errmsg = wechat_data.errmsg.unwrap_or_default();
            error!("微信 code 换取 openid 失败: {} - {}", errcode, errmsg);
            return HttpResponse::BadRequest()
                .json(ErrorResponse::<()>::error(format!("微信登录失败: {}", errmsg)));
        }

        match wechat_data.openid {
            Some(o) => o,
            None => {
                return HttpResponse::InternalServerError()
                    .json(ErrorResponse::<()>::error("未获取到 openid"));
            }
        }
    };

    let user_id: i32 = match sqlx::query_as::<_, (i32,)>(
        r#"
        INSERT INTO users (openid, name, type)
        VALUES ($1, left($1, 8), 2)
        ON CONFLICT (openid) DO UPDATE SET id = users.id
        RETURNING id
        "#,
    )
    .bind(&openid)
    .fetch_one(pool.get_ref())
    .await
    {
        Ok((id,)) => id,
        Err(e) => {
            error!("用户创建/查询失败: {}", e);
            return HttpResponse::InternalServerError()
                .json(ErrorResponse::<()>::error("用户处理失败"));
        }
    };

    let token = match generate_token(user_id, &openid, 2, &app_state.jwt_secret) {
        Ok(t) => t,
        Err(e) => {
            error!("JWT 生成失败: {}", e);
            return HttpResponse::InternalServerError()
                .json(ErrorResponse::<()>::error("生成令牌失败"));
        }
    };

    let (is_paid_active, paid_expires_at): (bool, Option<String>) =
        match sqlx::query_as::<_, (bool, Option<chrono::DateTime<chrono::Utc>>)>(
            "SELECT is_paid_active($1)",
        )
        .bind(user_id)
        .fetch_optional(pool.get_ref())
        .await
        {
            Ok(Some((active, expires))) => (active, expires.map(|e| e.to_rfc3339())),
            _ => (false, None),
        };

    let base_url = std::env::var("APP_BASE_URL")
        .unwrap_or_else(|_| "https://dev.xmclassmate.top".to_string());
    let payment_url = if is_paid_active {
        None
    } else {
        Some(format!("{}/payment?jwt={}", base_url, token))
    };

    info!("[WEB LOGIN AUTO-CONFIRM] user_id={} is_paid={}", user_id, is_paid_active);
    HttpResponse::Ok().json(AutoConfirmResponse {
        success: true,
        token: Some(token),
        is_paid_active,
        paid_expires_at,
        payment_url,
    })
}
