use super::{type_map, FieldDef};

pub fn gen_create(pascal: &str, fields: &[FieldDef]) -> String {
    let mut field_lines = String::new();
    for f in fields {
        let tm = type_map(&f.field_type);
        let base_t = match f.field_type.as_str() {
            "datetime" | "date" => "String",
            "json" => "serde_json::Value",
            _ => tm.rust_type,
        };
        if f.optional {
            let opt_attr = tm
                .validate_attr
                .trim_start_matches("#[validate(")
                .trim_end_matches(")]");
            let attr = if opt_attr.is_empty() {
                String::new()
            } else {
                format!("    #[validate(optional, {opt_attr})]\n")
            };
            field_lines.push_str(&attr);
            field_lines.push_str(&format!("    pub {}: Option<{}>,\n", f.name, base_t));
        } else {
            if !tm.validate_attr.is_empty() {
                field_lines.push_str(&format!("    {}\n", tm.validate_attr));
            }
            field_lines.push_str(&format!("    pub {}: {},\n", f.name, base_t));
        }
    }

    format!(
        "use rok_validate::Validate;\nuse serde::Deserialize;\n\n#[derive(Deserialize, Validate)]\npub struct Create{pascal}Request {{\n{field_lines}}}\n"
    )
}

pub fn gen_update(pascal: &str, fields: &[FieldDef]) -> String {
    let mut field_lines = String::new();
    for f in fields {
        let tm = type_map(&f.field_type);
        let rust_t = match f.field_type.as_str() {
            "datetime" => "String",
            "date" => "String",
            "json" => "serde_json::Value",
            _ => tm.rust_type,
        };
        field_lines.push_str(&format!("    pub {}: Option<{}>,\n", f.name, rust_t));
    }

    format!(
        "use rok_validate::Validate;\nuse serde::Deserialize;\n\n#[derive(Deserialize, Validate)]\npub struct Update{pascal}Request {{\n{field_lines}}}\n"
    )
}
