use sqlx::{PgPool, postgres::PgPoolOptions};
use std::env;
use std::error::Error;
use chrono::Utc;

// 从 models 模块引入 WeatherData 结构体
use crate::models::{User, WeatherData, WeatherDataBrief, WeatherListResponse};

// 用于插入weather_data的数据
pub async fn insert_weather_data(pool: &PgPool, weather_data: &WeatherData, user_id: i32) -> Result<i32, String> {
    // 配额检查：非付费用户数据条数限制
    let user = get_user_by_id(pool, user_id).await?;
    let is_paid_active = user.is_paid && (user.paid_expires_at.is_none() || user.paid_expires_at.unwrap() > Utc::now());
    
    if !is_paid_active {
        let current_count = count_user_weather_data(pool, user_id).await?;
        let limit: i64 = env::var("FREE_USER_DATA_LIMIT")
            .unwrap_or_else(|_| "20".to_string())
            .parse()
            .unwrap_or(20);
        
        if current_count >= limit {
            return Err("数据条数已达上限，请升级为付费用户".to_string());
        }
    }

    // 准备插入数据的 SQL 语句
    let insert_query = r#"
        INSERT INTO weather_data (
            user_id, title, date, hour, min, longitude, latitude, daysincejanfirst,
            theta, solardeclination, sunaltitude, overallcloudiness, lowcloudiness,
            cloudindex, solarradiationlevel, hasmeasuredwindspeed, measuredwindspeed,
            convertedwindspeed, pointheight, areatype, pointwindspeed,
            atmosphericstability, suitabilitydegree, winddirection, averagewinddirection,
            winddirectionstandarddeviation, windspeed, averagewindspeed, windspeedsuitability,
            winddirectionsuitability, overallsuitability, inspectiontype, assignmentnumber,
            calculatedwindspeed, hasspotcheckwindspeed, version
        ) VALUES (
            $1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19,
            $20, $21, $22, $23, $24, $25, $26, $27, $28, $29, $30, $31, $32, $33, $34, $35, $36
        ) RETURNING id
    "#;

    // 3. 执行插入操作
    let inserted_id = match sqlx::query_as::<_, (i32,)>(insert_query)
        .bind(user_id)
        .bind(&weather_data.title)
        .bind(weather_data.date)
        .bind(weather_data.hours)
        .bind(weather_data.min)
        .bind(&weather_data.longitude)
        .bind(&weather_data.latitude)
        .bind(weather_data.day_since_jan_first)
        .bind(weather_data.theta)
        .bind(weather_data.solar_declination)
        .bind(weather_data.sun_altitude)
        .bind(&weather_data.overall_cloudiness)
        .bind(&weather_data.low_cloudiness)
        .bind(&weather_data.cloud_index)
        .bind(weather_data.solar_radiation_level)
        .bind(weather_data.has_measured_wind_speed)
        .bind(weather_data.measured_wind_speed) // <-- 修改: 直接绑定 Option<f64>
        .bind(weather_data.converted_wind_speed) // <-- 修改: 直接绑定 Option<i32>，并移除 `as i32`
        .bind(weather_data.point_height) // <-- 修改: 直接绑定 Option<f64>
        .bind(&weather_data.area_type)
        .bind(weather_data.point_wind_speed) // <-- 修改: 直接绑定 Option<f64>
        .bind(&weather_data.atmospheric_stability)
        .bind(&weather_data.suitability_degree)
        .bind(
            serde_json::to_value(&weather_data.wind_direction)
                .map_err(|e| format!("JSON 序列化失败: {}", e))?,
        )
        .bind(weather_data.average_wind_direction)
        .bind(weather_data.wind_direction_standard_deviation)
        .bind(
            serde_json::to_value(&weather_data.wind_speed)
                .map_err(|e| format!("JSON 序列化失败: {}", e))?,
        )
        .bind(weather_data.average_wind_speed)
        .bind(&weather_data.wind_speed_suitability)
        .bind(&weather_data.wind_direction_suitability)
        .bind(&weather_data.overall_suitability)
        .bind(&weather_data.inspection_type)
        .bind(&weather_data.assignment_number)
        .bind(weather_data.calculated_wind_speed) // 这个本来就是 Option，无需修改
        .bind(weather_data.has_spot_check_wind_speed)
        .bind(&weather_data.version)
        .fetch_one(pool)
        .await
    {
        Ok((id,)) => id,
        Err(e) => {
            return Err(format!("插入数据失败: {}", e));
        }
    };

    // 4. 成功，返回插入的 ID
    Ok(inserted_id)
}

pub async fn create_pool() -> Result<PgPool, Box<dyn Error>> {
    // 获取数据库URL并提供友好错误信息
    let database_url =
        env::var("DATABASE_URL").map_err(|_| "环境变量DATABASE_URL未设置，请在.env文件中配置")?;

    // 配置连接池参数
    let pool = PgPoolOptions::new()
        .max_connections(20) // 根据应用需求调整最大连接数
        .acquire_timeout(std::time::Duration::from_secs(30)) // 获取连接的超时时间
        .connect(&database_url)
        .await
        .map_err(|e| format!("数据库连接失败: {}", e))?;

    Ok(pool)
}

// 获取天气数据详情
pub async fn get_weather_details(pool: &PgPool, weather_id: i32) -> Result<WeatherData, String> {
    let query = r#"
        SELECT 
            wd.id, wd.title, wd.date, wd.hour, wd.min, 
            wd.longitude, wd.latitude,
            wd.daysincejanfirst, wd.theta, wd.solardeclination,
            wd.sunaltitude, wd.overallcloudiness, wd.lowcloudiness,
            wd.cloudindex, wd.solarradiationlevel, wd.hasmeasuredwindspeed,
            wd.measuredwindspeed, wd.convertedwindspeed, wd.pointheight,
            wd.areatype, wd.pointwindspeed, wd.atmosphericstability,
            wd.suitabilitydegree, wd.winddirection, wd.averagewinddirection,
            wd.winddirectionstandarddeviation, wd.windspeed, wd.averagewindspeed,
            wd.windspeedsuitability, wd.winddirectionsuitability, wd.overallsuitability,
            wd.inspectiontype, wd.assignmentnumber, wd.calculatedwindspeed, wd.hasspotcheckwindspeed,
            u.openid, wd.version
        FROM weather_data wd
        JOIN users u ON wd.user_id = u.id
        WHERE wd.id = $1
    "#;

    let row = match sqlx::query_as::<_, WeatherData>(query)
        .bind(weather_id)
        .fetch_optional(pool)
        .await
    {
        Ok(Some(row)) => row,
        Ok(None) => return Err(format!("未找到ID为 {} 的天气数据", weather_id)),
        Err(e) => return Err(format!("查询天气数据失败: {}", e)),
    };

    Ok(row)
}

// get_weather_list函数
pub async fn get_weather_list(
    pool: &PgPool,
    user_id: i32,
    page: i32,
    limit: i32,
) -> Result<WeatherListResponse, String> {
    let offset = (page - 1) * limit;

    // 1. 查询符合条件的总条数
    let total_query = r#"
        SELECT COUNT(*) as total 
        FROM weather_data 
        WHERE user_id = $1
    "#;
    let total = match sqlx::query_as::<_, (i64,)>(total_query)
        .bind(user_id)
        .fetch_one(pool)
        .await
    {
        Ok((count,)) => count,
        Err(e) => return Err(format!("查询总条数失败: {}", e)),
    };

    // 2. 查询当前页数据列表
    let list_query = r#"
        SELECT 
            wd.id, wd.title, wd.date, wd.hour, wd.min, wd.longitude, wd.latitude
        FROM weather_data wd
        WHERE wd.user_id = $1
        ORDER BY wd.date DESC, wd.hour DESC, wd.min DESC
        LIMIT $2 OFFSET $3
    "#;
    let list = match sqlx::query_as::<_, WeatherDataBrief>(list_query)
        .bind(user_id)
        .bind(limit)
        .bind(offset)
        .fetch_all(pool)
        .await
    {
        Ok(data) => data,
        Err(e) => return Err(format!("查询天气数据列表失败: {}", e)),
    };

    // 3. 包装结果并返回
    Ok(WeatherListResponse { list, total })
}

pub async fn delete_weather_data(
    pool: &PgPool,
    weather_id: i32,
    user_id: i32,
) -> Result<(), String> {
    let query = r#"
        DELETE FROM weather_data 
        WHERE id = $1 AND user_id = $2
    "#;

    let result = sqlx::query(query)
        .bind(weather_id)
        .bind(user_id)
        .execute(pool)
        .await
        .map_err(|e| format!("删除天气数据失败: {}", e))?;

    if result.rows_affected() == 0 {
        return Err(format!("未找到ID为 {} 的天气数据或无权限删除", weather_id));
    }

    Ok(())
}

// 根据用户ID获取用户信息
pub async fn get_user_by_id(pool: &PgPool, user_id: i32) -> Result<User, String> {
    let query = r#"
        SELECT 
            id, name, openid, phone, type, "desc", is_paid, is_admin, paid_expires_at,
            avatar_url, nickname
        FROM users
        WHERE id = $1
    "#;

    let row = match sqlx::query_as::<_, User>(query)
        .bind(user_id)
        .fetch_optional(pool)
        .await
    {
        Ok(Some(row)) => row,
        Ok(None) => return Err(format!("未找到ID为 {} 的用户", user_id)),
        Err(e) => return Err(format!("查询用户信息失败: {}", e)),
    };

    Ok(row)
}

// 统计用户的天气数据条数
pub async fn count_user_weather_data(pool: &PgPool, user_id: i32) -> Result<i64, String> {
    let query = r#"
        SELECT COUNT(*) FROM weather_data WHERE user_id = $1
    "#;

    let count = match sqlx::query_as::<_, (i64,)>(query)
        .bind(user_id)
        .fetch_one(pool)
        .await
    {
        Ok((count,)) => count,
        Err(e) => return Err(format!("查询天气数据条数失败: {}", e)),
    };

    Ok(count)
}

// 更新用户付费状态
pub async fn update_user_payment_status(
    pool: &PgPool,
    user_id: i32,
    is_paid: bool,
    paid_expires_at: Option<chrono::DateTime<chrono::Utc>>,
) -> Result<(), String> {
    let query = r#"
        UPDATE users 
        SET is_paid = $1, paid_expires_at = $2 
        WHERE id = $3
    "#;

    match sqlx::query(query)
        .bind(is_paid)
        .bind(paid_expires_at)
        .bind(user_id)
        .execute(pool)
        .await
    {
        Ok(_) => Ok(()),
        Err(e) => Err(format!("更新用户付费状态失败: {}", e)),
    }
}

// 更新用户个人信息
pub async fn update_user_profile(
    pool: &PgPool,
    user_id: i32,
    nickname: &Option<String>,
    avatar_url: &Option<String>,
) -> Result<(), String> {
    let query = r#"
        UPDATE users 
        SET nickname = COALESCE($1, nickname),
            avatar_url = COALESCE($2, avatar_url)
        WHERE id = $3
    "#;

    match sqlx::query(query)
        .bind(nickname)
        .bind(avatar_url)
        .bind(user_id)
        .execute(pool)
        .await
    {
        Ok(_) => Ok(()),
        Err(e) => Err(format!("更新用户个人信息失败: {}", e)),
    }
}
