use serde::{Deserialize, Serialize};

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Schema {
    pub tables: Vec<Table>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Table {
    pub name: String,
    pub columns: Vec<Column>,

    #[serde(default)]
    pub indexes: Vec<Index>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Column {
    pub name: String,
    #[serde(rename = "type")]
    pub col_type: LogicalType,

    #[serde(default = "default_nullable")]
    pub nullable: bool,

    #[serde(default)]
    pub primary_key: bool,

    #[serde(default)]
    pub unique: bool,

    #[serde(default)]
    pub default: Option<ColumnDefault>,
}

fn default_nullable() -> bool {
    true
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum ColumnDefault {
    Sql { sql: String },
    Value(DefaultLiteral),
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum DefaultLiteral {
    Bool(bool),
    Int(i64),
    String(String),
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Index {
    pub name: String,
    pub columns: Vec<String>,

    #[serde(default)]
    pub unique: bool,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum LogicalType {
    String,
    Int64,
    Bool,
    Uuid,
    Timestamp,
}
