use crate::{APICategory, AccessBucket, DatabaseKind,  FileRouterScope, Logical, Operator, OwnerKind, PermtKind, RoleKind};

#[derive(Debug, serde::Serialize, serde::Deserialize, PartialEq, Clone)]
pub enum SqlValue {
    Num(i64),
    Float(f64),
    Str(String),
    UtcTime(::chrono::DateTime<::chrono::Utc>),
    Time(::chrono::NaiveTime),
    Date(::chrono::NaiveDate),
    DateTime(::chrono::NaiveDateTime),
    Bool(bool),
    Buff(Vec<u8>),
    Json(serde_json::Value),
    Null,
}

pub trait IntoSqlValue {
    fn into_sql_value(self) -> SqlValue;
}


pub struct SqlOf<T: IntoSqlValue>(pub T);

impl<T: IntoSqlValue> From<SqlOf<T>> for SqlValue {
    fn from(v: SqlOf<T>) -> Self {
        v.0.into_sql_value()
    }
}


pub enum ValueEnum {
    Num,
    Float,
    Str,
    UtcTime,
    Time,
    Date,
    DateTime,
    Bool,
    Buff,
    Json,
    Null,
}

#[derive(Debug, serde::Serialize, serde::Deserialize, PartialEq, Clone)]
pub enum WhereValue {
    Value(SqlValue),
    List(Vec<SqlValue>),
}

// 实现into
impl<T> From<T> for WhereValue
where
    T: Into<SqlValue>,
{
    fn from(v: T) -> Self {
        WhereValue::Value(v.into())
    }
}

impl<T> From<Vec<T>> for WhereValue
where
    T: Into<SqlValue>,
{
    fn from(v: Vec<T>) -> Self {
        WhereValue::List(v.into_iter().map(|item| item.into()).collect())
    }
}

/// &[T] 泛型实现，支持 Clone
impl<T> From<&[T]> for WhereValue
where
    T: Into<SqlValue> + Clone,
{
    fn from(v: &[T]) -> Self {
        WhereValue::List(v.iter().cloned().map(|item| item.into()).collect())
    }
}

impl From<DatabaseKind> for SqlValue {
    fn from(v: DatabaseKind) -> Self {
        SqlValue::Str(v.to_string())
    }
}
impl From<&DatabaseKind> for SqlValue {
    fn from(v: &DatabaseKind) -> Self {
        SqlValue::Str(v.to_string())
    }
}

impl From<RoleKind> for SqlValue {
    fn from(v: RoleKind) -> Self {
        SqlValue::Str(v.to_string().to_lowercase())
    }
}

impl From<&RoleKind> for SqlValue {
    fn from(v: &RoleKind) -> Self {
        SqlValue::Str(v.to_string().to_lowercase())
    }
}

impl From<AccessBucket> for SqlValue {
    fn from(v: AccessBucket) -> Self {
        SqlValue::Str(v.to_string().to_lowercase())
    }
}

impl From<&AccessBucket> for SqlValue {
    fn from(v: &AccessBucket) -> Self {
        SqlValue::Str(v.to_string().to_lowercase())
    }
}

impl From<&FileRouterScope> for SqlValue {
    fn from(v: &FileRouterScope) -> Self {
        SqlValue::Str(v.to_string().to_lowercase())
    }
}

impl From<FileRouterScope> for SqlValue {
    fn from(v: FileRouterScope) -> Self {
        SqlValue::Str(v.to_string().to_lowercase())
    }
}


#[cfg(any(feature = "postgres", feature = "mysql", feature = "sqlite"))]
impl<T> From<::sqlx::types::Json<T>> for SqlValue
where
    T: serde::Serialize,
{
    fn from(v: ::sqlx::types::Json<T>) -> Self {
        // 直接序列化内部结构为 serde_json::Value
        let json_value = serde_json::to_value(v.0).unwrap_or(serde_json::Value::Null);
        SqlValue::Json(json_value)
    }
}

impl From<PermtKind> for SqlValue {
    fn from(v: PermtKind) -> Self {
        SqlValue::Str(v.to_string().to_lowercase())
    }
}

impl From<&PermtKind> for SqlValue {
    fn from(v: &PermtKind) -> Self {
        SqlValue::Str(v.to_string().to_lowercase())
    }
}

impl From<OwnerKind> for SqlValue {
    fn from(v: OwnerKind) -> Self {
        SqlValue::Str(v.to_string().to_lowercase())
    }
}

impl From<&OwnerKind> for SqlValue {
    fn from(v: &OwnerKind) -> Self {
        SqlValue::Str(v.to_string().to_lowercase())
    }
}

impl From<APICategory> for SqlValue {
    fn from(v: APICategory) -> Self {
        SqlValue::Str(v.to_string().to_lowercase())
    }
}

impl From<&APICategory> for SqlValue {
    fn from(v: &APICategory) -> Self {
        SqlValue::Str(v.to_string().to_lowercase())
    }
}

#[test]
fn dev() {
    let res = APICategory::Auth.to_string();
    println!("{res}");
}

impl From<::chrono::DateTime<::chrono::Utc>> for SqlValue {
    fn from(v: ::chrono::DateTime<::chrono::Utc>) -> Self {
        SqlValue::UtcTime(v)
    }
}
impl From<&::chrono::DateTime<::chrono::Utc>> for SqlValue {
    fn from(v: &::chrono::DateTime<::chrono::Utc>) -> Self {
        SqlValue::UtcTime(v.to_owned())
    }
}

impl From<::chrono::NaiveTime> for SqlValue {
    fn from(v: ::chrono::NaiveTime) -> Self {
        SqlValue::Time(v)
    }
}
impl From<&::chrono::NaiveTime> for SqlValue {
    fn from(v: &::chrono::NaiveTime) -> Self {
        SqlValue::Time(v.to_owned())
    }
}


impl From<::chrono::NaiveDate> for SqlValue {
    fn from(v: ::chrono::NaiveDate) -> Self {
        SqlValue::Date(v)
    }
}

impl From<&::chrono::NaiveDate> for SqlValue {
    fn from(v: &::chrono::NaiveDate) -> Self {
        SqlValue::Date(v.to_owned())
    }
}

impl From<::chrono::NaiveDateTime> for SqlValue {
    fn from(v: ::chrono::NaiveDateTime) -> Self {
        SqlValue::DateTime(v)
    }
}

impl From<&::chrono::NaiveDateTime> for SqlValue {
    fn from(v: &::chrono::NaiveDateTime) -> Self {
        SqlValue::DateTime(v.to_owned())
    }
}
impl From<serde_json::Value> for SqlValue {
    fn from(v: serde_json::Value) -> Self {
        SqlValue::Json(v)
    }
}
impl From<&serde_json::Value> for SqlValue {
    fn from(v: &serde_json::Value) -> Self {
        SqlValue::Json(v.clone())
    }
}

impl From<i32> for SqlValue {
    fn from(v: i32) -> Self {
        SqlValue::Num(v as i64)
    }
}
impl From<&i32> for SqlValue {
    fn from(v: &i32) -> Self {
        SqlValue::Num(*v as i64)
    }
}

impl From<i64> for SqlValue {
    fn from(v: i64) -> Self {
        SqlValue::Num(v)
    }
}
impl From<&i64> for SqlValue {
    fn from(v: &i64) -> Self {
        SqlValue::Num(*v as i64)
    }
}
impl From<u64> for SqlValue {
    fn from(v: u64) -> Self {
        SqlValue::Num(v as i64)
    }
}

impl From<&u64> for SqlValue {
    fn from(v: &u64) -> Self {
        SqlValue::Num(*v as i64)
    }
}
impl From<f64> for SqlValue {
    fn from(v: f64) -> Self {
        SqlValue::Float(v)
    }
}
impl From<&f64> for SqlValue {
    fn from(v: &f64) -> Self {
        SqlValue::Float(*v)
    }
}

impl From<bool> for SqlValue {
    fn from(v: bool) -> Self {
        SqlValue::Bool(v)
    }
}
impl From<&bool> for SqlValue {
    fn from(v: &bool) -> Self {
        SqlValue::Bool(*v)
    }
}

impl From<&str> for SqlValue {
    fn from(v: &str) -> Self {
        SqlValue::Str(v.to_string())
    }
}

impl From<String> for SqlValue {
    fn from(v: String) -> Self {
        SqlValue::Str(v)
    }
}
impl From<&String> for SqlValue {
    fn from(v: &String) -> Self {
        SqlValue::Str(v.to_string())
    }
}
impl From<Vec<u8>> for SqlValue {
    fn from(v: Vec<u8>) -> Self {
        SqlValue::Buff(v)
    }
}

impl From<&[u8]> for SqlValue {
    fn from(v: &[u8]) -> Self {
        SqlValue::Buff(v.to_vec())
    }
}

impl<T: Into<SqlValue> + Clone> From<&Option<T>> for SqlValue {
    fn from(opt: &Option<T>) -> Self {
        match opt {
            | Some(v) => v.clone().into(),
            | None => SqlValue::Null,
        }
    }
}


impl<T> From<Option<T>> for SqlValue 
where 
    SqlValue: From<T>,  // 更清晰：SqlValue 能从 T 构造
{
    fn from(opt: Option<T>) -> Self {
        match opt {
            Some(v) => Self::from(v),  // 或 v.into()
            None => SqlValue::Null,
        }
    }
}


#[derive(Debug, serde::Serialize,  PartialEq, Clone,serde::Deserialize)]
pub struct BuildConditionItem {
    pub column: String,
    pub values: WhereValue,
    pub operator: Operator,
    pub logical: Logical,
}


fn _from_str(v: &str) -> SqlValue {
    // 尝试解析带时区的 UTC/ISO 8601 时间
    if let Ok(dt) = ::chrono::DateTime::parse_from_rfc3339(v) {
        return SqlValue::UtcTime(dt.with_timezone(&::chrono::Utc));
    }
    // 尝试解析本地日期时间
    if let Ok(dt) = ::chrono::NaiveDateTime::parse_from_str(v, "%Y-%m-%d %H:%M:%S") {
        return SqlValue::DateTime(dt);
    }
    // 尝试解析日期
    if let Ok(d) = ::chrono::NaiveDate::parse_from_str(v, "%Y-%m-%d") {
        return SqlValue::Date(d);
    }
    // 尝试解析时间
    if let Ok(t) = ::chrono::NaiveTime::parse_from_str(v, "%H:%M:%S") {
        return SqlValue::Time(t);
    }
    // 默认当作普通字符串
    SqlValue::Str(v.to_string())
}
