use proc_macro::TokenStream;
use quote::quote;
use syn::{
    parse_macro_input, Attribute, Data, DeriveInput, Fields, GenericArgument, PathArguments, Type,
};

use crate::column_attr::{ColumnOpts, FieldInfo, RelationOpts};

pub fn derive_model_impl(input: TokenStream) -> TokenStream {
    let input = parse_macro_input!(input as DeriveInput);
    let struct_name = &input.ident;

    let model_attrs = parse_model_attrs(&input.attrs);
    let table_name = model_attrs
        .table_name
        .unwrap_or_else(|| struct_name.to_string().to_lowercase() + "s");

    let fields = match &input.data {
        Data::Struct(data) => match &data.fields {
            Fields::Named(fields) => fields,
            _ => panic!("Model derive only supports structs with named fields"),
        },
        _ => panic!("Model derive only supports structs"),
    };

    let field_infos: Vec<FieldInfo> = fields
        .named
        .iter()
        .filter_map(|f| {
            let field_name = f.ident.clone()?;
            let field_type = f.ty.clone();
            let opts = ColumnOpts::from_attrs(&f.attrs);
            let relation_opts = RelationOpts::from_attrs(&f.attrs);

            let is_column = opts.is_some();
            let opts = opts.unwrap_or_default();
            let column_name = opts
                .column_name
                .clone()
                .unwrap_or_else(|| field_name.to_string());

            Some(FieldInfo {
                field_name,
                field_type,
                column_name,
                opts,
                is_column,
                relation_opts,
            })
        })
        .collect();

    let column_fields: Vec<&FieldInfo> = field_infos.iter().filter(|f| f.is_column).collect();

    let columns_struct_name =
        syn::Ident::new(&format!("{}Columns", struct_name), struct_name.span());

    // Generate the XColumns struct fields
    let columns_struct_fields = column_fields.iter().map(|f| {
        let name = &f.field_name;
        let ty = inner_type_of_option(&f.field_type).unwrap_or(&f.field_type);
        quote! {
            pub #name: litedbmodel::column::Column<#ty>
        }
    });

    // Generate the columns() constructor
    let columns_init_fields = column_fields.iter().map(|f| {
        let name = &f.field_name;
        let col_name = &f.column_name;
        quote! {
            #name: litedbmodel::column::Column::new(#table_name, #col_name)
        }
    });

    // Generate column metadata
    let column_meta_items = column_fields.iter().map(|f| {
        let col_name = &f.column_name;
        let prop_name = f.field_name.to_string();
        let pk = f.opts.primary_key;
        let ai = f.opts.auto_increment;
        let has_default = f.opts.has_default;
        let sql_cast = match &f.opts.sql_cast {
            Some(s) => quote! { Some(#s) },
            None => quote! { None },
        };
        let type_cast = match &f.opts.type_cast {
            Some(s) => quote! { Some(#s) },
            None => quote! { None },
        };
        quote! {
            litedbmodel::model::ColumnMeta {
                column_name: #col_name,
                property_name: #prop_name,
                primary_key: #pk,
                auto_increment: #ai,
                sql_cast: #sql_cast,
                type_cast: #type_cast,
                has_default: #has_default,
            }
        }
    });

    // Primary key column names
    let pkey_columns: Vec<&str> = column_fields
        .iter()
        .filter(|f| f.opts.primary_key)
        .map(|f| f.column_name.as_str())
        .collect();
    let pkey_count = pkey_columns.len();
    let pkey_column_literals = pkey_columns.iter().map(|name| {
        quote! { #name }
    });

    // FromRow implementation
    let from_row_fields = field_infos.iter().map(|f| {
        let name = &f.field_name;
        let col_name = &f.column_name;
        if f.is_column {
            let ty = &f.field_type;
            if is_option_type(ty) {
                let inner_ty = inner_type_of_option(ty).unwrap();
                quote! {
                    #name: row.get(#col_name)
                        .and_then(|v| if v.is_null() { None } else { <#inner_ty as FromValue>::from_value(v.clone()) })
                }
            } else {
                quote! {
                    #name: row.get(#col_name)
                        .and_then(|v| <#ty as FromValue>::from_value(v.clone()))
                        .unwrap_or_default()
                }
            }
        } else {
            quote! {
                #name: Default::default()
            }
        }
    });

    let meta_count = column_fields.len();

    // Generate relation metadata
    let relation_fields: Vec<&FieldInfo> = field_infos
        .iter()
        .filter(|f| f.relation_opts.is_some())
        .collect();

    let relation_meta_items = relation_fields.iter().map(|f| {
        let ro = f.relation_opts.as_ref().unwrap();
        let name = f.field_name.to_string();
        let rel_type_expr = match ro.relation_type.as_str() {
            "has_many" => quote! { litedbmodel::relation::RelationType::HasMany },
            "belongs_to" => quote! { litedbmodel::relation::RelationType::BelongsTo },
            "has_one" => quote! { litedbmodel::relation::RelationType::HasOne },
            _ => unreachable!(),
        };
        let target_tbl_expr = match &ro.target_table {
            Some(tbl) => quote! { #tbl },
            None => {
                let inner_type = extract_inner_model_type(&f.field_type)
                    .unwrap_or_else(|| panic!(
                        "Cannot infer target model type from field '{}'. Specify table = \"...\" explicitly.",
                        f.field_name
                    ));
                quote! { <#inner_type as litedbmodel::model::Model>::TABLE_NAME }
            }
        };
        let order_expr = match &ro.order {
            Some(o) => quote! { Some(#o) },
            None => quote! { None },
        };
        let limit_per_parent_expr = match &ro.limit_per_parent {
            Some(n) => quote! { Some(#n) },
            None => quote! { None },
        };
        let hard_limit_expr = match &ro.hard_limit {
            Some(n) => quote! { Some(#n) },
            None => quote! { None },
        };
        let key_pairs_entries: Vec<proc_macro2::TokenStream> = ro.key_pairs
            .iter()
            .map(|(s, t)| {
                let s_lit = syn::LitStr::new(s, proc_macro2::Span::call_site());
                let t_lit = syn::LitStr::new(t, proc_macro2::Span::call_site());
                quote! { (#s_lit, #t_lit) }
            })
            .collect();
        let key_pairs_expr = quote! { &[#(#key_pairs_entries),*] };
        quote! {
            litedbmodel::relation::RelationMeta {
                name: #name,
                relation_type: #rel_type_expr,
                key_pairs: #key_pairs_expr,
                target_table: #target_tbl_expr,
                order: #order_expr,
                limit_per_parent: #limit_per_parent_expr,
                hard_limit: #hard_limit_expr,
            }
        }
    });

    let relation_count = relation_fields.len();

    // Generate setup_batch_loading for lazy relation loading
    let setup_batch_loading_impl = if relation_fields.is_empty() {
        quote! {}
    } else {
        let batch_setup_blocks: Vec<proc_macro2::TokenStream> = relation_fields
            .iter()
            .map(|f| {
                let ro = f.relation_opts.as_ref().unwrap();
                let relation_field_name = &f.field_name;

                let child_type = extract_inner_model_type(&f.field_type).unwrap_or_else(|| {
                    panic!(
                        "Cannot extract child model type from relation field '{}'",
                        relation_field_name
                    )
                });

                let target_tbl_expr = match &ro.target_table {
                    Some(tbl) => quote! { #tbl },
                    None => quote! { <#child_type as litedbmodel::model::Model>::TABLE_NAME },
                };

                let is_has_many = ro.relation_type == "has_many";
                let is_composite = ro.key_pairs.len() > 1;

                let source_field_idents: Vec<&syn::Ident> = ro
                    .key_pairs
                    .iter()
                    .map(|(src_col, _)| {
                        &column_fields
                            .iter()
                            .find(|cf| cf.column_name == *src_col)
                            .unwrap_or_else(|| {
                                panic!(
                                    "Relation '{}': source column '{}' not found in model columns",
                                    relation_field_name, src_col
                                )
                            })
                            .field_name
                    })
                    .collect();

                let target_col_names: Vec<&str> =
                    ro.key_pairs.iter().map(|(_, t)| t.as_str()).collect();

                match (is_has_many, is_composite) {
                    (true, false) => {
                        let tgt_col = target_col_names[0];
                        let src_field = source_field_idents[0];
                        let order_expr = match &ro.order {
                            Some(o) => quote! { Some(#o) },
                            None => quote! { None },
                        };
                        let lpp_expr = match ro.limit_per_parent {
                            Some(n) => {
                                let n_lit = syn::LitInt::new(&n.to_string(), proc_macro2::Span::call_site());
                                quote! { Some(#n_lit) }
                            }
                            None => quote! { None },
                        };
                        let hl_expr = match ro.hard_limit {
                            Some(n) => {
                                let n_lit = syn::LitInt::new(&n.to_string(), proc_macro2::Span::call_site());
                                quote! { Some(#n_lit) }
                            }
                            None => quote! { None },
                        };
                        quote! {
                            {
                                let mut unique_keys: Vec<litedbmodel::values::Value> = Vec::new();
                                let mut seen = std::collections::HashSet::new();
                                for record in records.iter() {
                                    let key = litedbmodel::values::Value::from(record.#src_field.clone());
                                    if key.is_null() { continue; }
                                    let key_str = litedbmodel::relation::value_to_key(&key);
                                    if seen.insert(key_str) {
                                        unique_keys.push(key);
                                    }
                                }
                                let batch_executor = executor.clone();
                                let batch_keys = unique_keys;
                                let batch_lc = limit_config.cloned();
                                let batch = std::sync::Arc::new(litedbmodel::relation::RelationBatch::new(
                                    Box::new(move || {
                                        let ex = batch_executor.clone();
                                        let keys = batch_keys.clone();
                                        let lc = batch_lc.clone();
                                        Box::pin(async move {
                                            litedbmodel::relation::batch_load_has_many::<#child_type>(
                                                &*ex, &keys, #target_tbl_expr, #tgt_col,
                                                #order_expr, #lpp_expr, #hl_expr, lc.as_ref(),
                                            ).await
                                        })
                                    })
                                ));
                                for record in records.iter_mut() {
                                    let key = litedbmodel::values::Value::from(record.#src_field.clone());
                                    if key.is_null() {
                                        record.#relation_field_name.set(Vec::new());
                                    } else {
                                        let key_str = litedbmodel::relation::value_to_key(&key);
                                        record.#relation_field_name.set_batch(batch.clone(), key_str);
                                    }
                                }
                            }
                        }
                    }
                    (true, true) => {
                        let tgt_col_lits: Vec<_> =
                            target_col_names.iter().map(|t| quote! { #t }).collect();
                        let get_key_values: Vec<_> = source_field_idents
                            .iter()
                            .map(|fi| quote! { litedbmodel::values::Value::from(record.#fi.clone()) })
                            .collect();
                        let order_expr = match &ro.order {
                            Some(o) => quote! { Some(#o) },
                            None => quote! { None },
                        };
                        let lpp_expr = match ro.limit_per_parent {
                            Some(n) => {
                                let n_lit = syn::LitInt::new(&n.to_string(), proc_macro2::Span::call_site());
                                quote! { Some(#n_lit) }
                            }
                            None => quote! { None },
                        };
                        let hl_expr = match ro.hard_limit {
                            Some(n) => {
                                let n_lit = syn::LitInt::new(&n.to_string(), proc_macro2::Span::call_site());
                                quote! { Some(#n_lit) }
                            }
                            None => quote! { None },
                        };
                        quote! {
                            {
                                let mut unique_tuples: Vec<Vec<litedbmodel::values::Value>> = Vec::new();
                                let mut seen = std::collections::HashSet::new();
                                for record in records.iter() {
                                    let key_vals = vec![#(#get_key_values),*];
                                    if key_vals.iter().any(|v| v.is_null()) { continue; }
                                    let key_str = litedbmodel::relation::composite_value_to_key(&key_vals);
                                    if seen.insert(key_str) {
                                        unique_tuples.push(key_vals);
                                    }
                                }
                                let batch_executor = executor.clone();
                                let batch_tuples = unique_tuples;
                                let batch_lc = limit_config.cloned();
                                let tgt_cols: &[&str] = &[#(#tgt_col_lits),*];
                                let batch = std::sync::Arc::new(litedbmodel::relation::RelationBatch::new(
                                    Box::new(move || {
                                        let ex = batch_executor.clone();
                                        let tuples = batch_tuples.clone();
                                        let lc = batch_lc.clone();
                                        Box::pin(async move {
                                            litedbmodel::relation::batch_load_has_many_composite::<#child_type>(
                                                &*ex, &tuples, #target_tbl_expr, tgt_cols,
                                                #order_expr, #lpp_expr, #hl_expr, lc.as_ref(),
                                            ).await
                                        })
                                    })
                                ));
                                for record in records.iter_mut() {
                                    let key_vals = vec![#(#get_key_values),*];
                                    if key_vals.iter().any(|v| v.is_null()) {
                                        record.#relation_field_name.set(Vec::new());
                                    } else {
                                        let key_str = litedbmodel::relation::composite_value_to_key(&key_vals);
                                        record.#relation_field_name.set_batch(batch.clone(), key_str);
                                    }
                                }
                            }
                        }
                    }
                    (false, false) => {
                        let tgt_col = target_col_names[0];
                        let src_field = source_field_idents[0];
                        quote! {
                            {
                                let mut unique_keys: Vec<litedbmodel::values::Value> = Vec::new();
                                let mut seen = std::collections::HashSet::new();
                                for record in records.iter() {
                                    let key = litedbmodel::values::Value::from(record.#src_field.clone());
                                    if key.is_null() { continue; }
                                    let key_str = litedbmodel::relation::value_to_key(&key);
                                    if seen.insert(key_str) {
                                        unique_keys.push(key);
                                    }
                                }
                                let batch_executor = executor.clone();
                                let batch_keys = unique_keys;
                                let batch = std::sync::Arc::new(litedbmodel::relation::RelationBatch::new(
                                    Box::new(move || {
                                        let ex = batch_executor.clone();
                                        let keys = batch_keys.clone();
                                        Box::pin(async move {
                                            litedbmodel::relation::batch_load_one::<#child_type>(
                                                &*ex, &keys, #target_tbl_expr, #tgt_col,
                                            ).await
                                        })
                                    })
                                ));
                                for record in records.iter_mut() {
                                    let key = litedbmodel::values::Value::from(record.#src_field.clone());
                                    if key.is_null() {
                                        record.#relation_field_name.set(None);
                                    } else {
                                        let key_str = litedbmodel::relation::value_to_key(&key);
                                        record.#relation_field_name.set_batch(batch.clone(), key_str);
                                    }
                                }
                            }
                        }
                    }
                    (false, true) => {
                        let tgt_col_lits: Vec<_> =
                            target_col_names.iter().map(|t| quote! { #t }).collect();
                        let get_key_values: Vec<_> = source_field_idents
                            .iter()
                            .map(|fi| quote! { litedbmodel::values::Value::from(record.#fi.clone()) })
                            .collect();
                        quote! {
                            {
                                let mut unique_tuples: Vec<Vec<litedbmodel::values::Value>> = Vec::new();
                                let mut seen = std::collections::HashSet::new();
                                for record in records.iter() {
                                    let key_vals = vec![#(#get_key_values),*];
                                    if key_vals.iter().any(|v| v.is_null()) { continue; }
                                    let key_str = litedbmodel::relation::composite_value_to_key(&key_vals);
                                    if seen.insert(key_str) {
                                        unique_tuples.push(key_vals);
                                    }
                                }
                                let batch_executor = executor.clone();
                                let batch_tuples = unique_tuples;
                                let tgt_cols: &[&str] = &[#(#tgt_col_lits),*];
                                let batch = std::sync::Arc::new(litedbmodel::relation::RelationBatch::new(
                                    Box::new(move || {
                                        let ex = batch_executor.clone();
                                        let tuples = batch_tuples.clone();
                                        Box::pin(async move {
                                            litedbmodel::relation::batch_load_one_composite::<#child_type>(
                                                &*ex, &tuples, #target_tbl_expr, tgt_cols,
                                            ).await
                                        })
                                    })
                                ));
                                for record in records.iter_mut() {
                                    let key_vals = vec![#(#get_key_values),*];
                                    if key_vals.iter().any(|v| v.is_null()) {
                                        record.#relation_field_name.set(None);
                                    } else {
                                        let key_str = litedbmodel::relation::composite_value_to_key(&key_vals);
                                        record.#relation_field_name.set_batch(batch.clone(), key_str);
                                    }
                                }
                            }
                        }
                    }
                }
            })
            .collect();

        quote! {
            fn setup_batch_loading(
                records: &mut [Self],
                executor: &dyn litedbmodel::model::Executor,
                limit_config: Option<&litedbmodel::types::LimitConfig>,
            ) {
                if records.is_empty() { return; }
                let executor: std::sync::Arc<dyn litedbmodel::model::Executor> = executor.clone_arc();
                #(#batch_setup_blocks)*
            }
        }
    };

    // update_table_name: use custom value or fall back to table_name
    let update_table_name = model_attrs
        .update_table_name
        .as_ref()
        .map(|s| quote! { #s })
        .unwrap_or_else(|| quote! { #table_name });

    // select_columns: use custom value or "*"
    let select_columns = model_attrs
        .select_columns
        .as_ref()
        .map(|s| quote! { #s })
        .unwrap_or_else(|| quote! { "*" });

    // default_order_raw: when set via order = "...", return Some("...")
    let default_order_raw = match &model_attrs.order {
        Some(s) => {
            let s_lit = syn::LitStr::new(s, proc_macro2::Span::call_site());
            quote! { Some(#s_lit) }
        }
        None => quote! { None },
    };

    // default_filter: when set, return Some(vec![Condition::Raw { sql, params }])
    let default_filter = match &model_attrs.default_filter {
        Some(sql) => {
            let sql_lit = syn::LitStr::new(sql, proc_macro2::Span::call_site());
            quote! {
                Some(vec![
                    litedbmodel::condition::Condition::Raw {
                        sql: #sql_lit.to_string(),
                        params: vec![],
                    }
                ])
            }
        }
        None => quote! { None },
    };

    // query_sql: when set via query = "...", return Some("...")
    let query_sql = match &model_attrs.query {
        Some(s) => {
            let s_lit = syn::LitStr::new(s, proc_macro2::Span::call_site());
            quote! { Some(#s_lit) }
        }
        None => quote! { None },
    };

    // Static SQL: build at macro expansion time for zero-cost fast path
    let select_cols_str = model_attrs.select_columns.as_deref().unwrap_or("*");
    let static_select = {
        let mut sql = String::new();
        if let Some(ref query) = model_attrs.query {
            sql.push_str(&format!("WITH {} AS ({}) ", table_name, query));
        }
        sql.push_str(&format!("SELECT {} FROM {}", select_cols_str, table_name));
        if let Some(ref filter) = model_attrs.default_filter {
            sql.push_str(&format!(" WHERE {}", filter));
        }
        if let Some(ref order) = model_attrs.order {
            sql.push_str(&format!(" ORDER BY {}", order));
        }
        sql
    };
    let static_select_lit = syn::LitStr::new(&static_select, proc_macro2::Span::call_site());

    let static_count = {
        let mut sql = String::new();
        if let Some(ref query) = model_attrs.query {
            sql.push_str(&format!("WITH {} AS ({}) ", table_name, query));
        }
        sql.push_str(&format!("SELECT COUNT(*) AS count FROM {}", table_name));
        if let Some(ref filter) = model_attrs.default_filter {
            sql.push_str(&format!(" WHERE {}", filter));
        }
        sql
    };
    let static_count_lit = syn::LitStr::new(&static_count, proc_macro2::Span::call_site());

    // PG fast path: column fields (field_name => "column_name") and non-column fields for Default
    let pg_column_entries = column_fields.iter().map(|f| {
        let name = &f.field_name;
        let col_name = &f.column_name;
        quote! { #name => #col_name }
    });
    let pg_default_fields = field_infos
        .iter()
        .filter(|f| !f.is_column)
        .map(|f| &f.field_name);

    let expanded = quote! {
        pub struct #columns_struct_name {
            #(#columns_struct_fields),*
        }

        impl litedbmodel::model::Model for #struct_name {
            type Columns = #columns_struct_name;

            const TABLE_NAME: &'static str = #table_name;

            fn update_table_name() -> &'static str {
                #update_table_name
            }

            fn select_columns() -> &'static str {
                #select_columns
            }

            fn default_filter() -> Option<Vec<litedbmodel::condition::Condition>> {
                #default_filter
            }

            fn default_order_raw() -> Option<&'static str> {
                #default_order_raw
            }

            fn query_sql() -> Option<&'static str> {
                #query_sql
            }

            fn static_select_sql() -> Option<&'static str> {
                Some(#static_select_lit)
            }

            fn static_count_sql() -> Option<&'static str> {
                Some(#static_count_lit)
            }

            fn column_meta() -> &'static [litedbmodel::model::ColumnMeta] {
                static META: [litedbmodel::model::ColumnMeta; #meta_count] = [
                    #(#column_meta_items),*
                ];
                &META
            }

            fn primary_key_columns() -> &'static [&'static str] {
                static PKEYS: [&str; #pkey_count] = [#(#pkey_column_literals),*];
                &PKEYS
            }

            fn columns() -> Self::Columns {
                #columns_struct_name {
                    #(#columns_init_fields),*
                }
            }

            litedbmodel::__pg_row_converter_impl!(#struct_name, { #(#pg_column_entries),* }, { #(#pg_default_fields),* });

            #setup_batch_loading_impl
        }

        impl litedbmodel::model::FromRow for #struct_name {
            fn from_row(row: &litedbmodel::driver::Row) -> litedbmodel::error::Result<Self> {
                use litedbmodel::values::{Value, FromValue};

                Ok(Self {
                    #(#from_row_fields),*
                })
            }
        }

        impl #struct_name {
            pub fn relation_meta() -> &'static [litedbmodel::relation::RelationMeta] {
                static META: [litedbmodel::relation::RelationMeta; #relation_count] = [
                    #(#relation_meta_items),*
                ];
                &META
            }

        }
    };

    TokenStream::from(expanded)
}

/// Parsed attributes from #[model(...)].
struct ModelAttrs {
    table_name: Option<String>,
    default_filter: Option<String>,
    select_columns: Option<String>,
    update_table_name: Option<String>,
    order: Option<String>,
    query: Option<String>,
}

fn parse_model_attrs(attrs: &[Attribute]) -> ModelAttrs {
    let mut table_name = None;
    let mut default_filter = None;
    let mut select_columns = None;
    let mut update_table_name = None;
    let mut order = None;
    let mut query = None;

    for attr in attrs {
        if attr.path().is_ident("model") {
            let _ = attr.parse_nested_meta(|meta| {
                if meta.path.is_ident("table") {
                    let value = meta.value()?;
                    let lit: syn::LitStr = value.parse()?;
                    table_name = Some(lit.value());
                } else if meta.path.is_ident("default_filter") {
                    let value = meta.value()?;
                    let lit: syn::LitStr = value.parse()?;
                    default_filter = Some(lit.value());
                } else if meta.path.is_ident("select_columns") {
                    let value = meta.value()?;
                    let lit: syn::LitStr = value.parse()?;
                    select_columns = Some(lit.value());
                } else if meta.path.is_ident("update_table_name") {
                    let value = meta.value()?;
                    let lit: syn::LitStr = value.parse()?;
                    update_table_name = Some(lit.value());
                } else if meta.path.is_ident("order") {
                    let value = meta.value()?;
                    let lit: syn::LitStr = value.parse()?;
                    order = Some(lit.value());
                } else if meta.path.is_ident("query") {
                    let value = meta.value()?;
                    let lit: syn::LitStr = value.parse()?;
                    query = Some(lit.value());
                }
                Ok(())
            });
        }
    }

    ModelAttrs {
        table_name,
        default_filter,
        select_columns,
        update_table_name,
        order,
        query,
    }
}

fn is_option_type(ty: &syn::Type) -> bool {
    if let syn::Type::Path(tp) = ty {
        if let Some(seg) = tp.path.segments.last() {
            return seg.ident == "Option";
        }
    }
    false
}

fn inner_type_of_option(ty: &syn::Type) -> Option<&syn::Type> {
    if let syn::Type::Path(tp) = ty {
        if let Some(seg) = tp.path.segments.last() {
            if seg.ident == "Option" {
                if let syn::PathArguments::AngleBracketed(args) = &seg.arguments {
                    if let Some(syn::GenericArgument::Type(inner)) = args.args.first() {
                        return Some(inner);
                    }
                }
            }
        }
    }
    None
}

/// Extract the inner model type from a relation field type.
/// `Relation<Vec<Post>>` → `Post`, `Relation<Option<User>>` → `User`, `Relation<User>` → `User`
fn extract_inner_model_type(ty: &Type) -> Option<Type> {
    let tp = match ty {
        Type::Path(tp) => tp,
        _ => return None,
    };
    let seg = tp.path.segments.last()?;
    if seg.ident != "Relation" {
        return None;
    }
    let args = match &seg.arguments {
        PathArguments::AngleBracketed(args) => args,
        _ => return None,
    };
    let inner = match args.args.first()? {
        GenericArgument::Type(t) => t,
        _ => return None,
    };
    if let Type::Path(inner_tp) = inner {
        let inner_seg = inner_tp.path.segments.last()?;
        if inner_seg.ident == "Vec" || inner_seg.ident == "Option" {
            if let PathArguments::AngleBracketed(inner_args) = &inner_seg.arguments {
                if let Some(GenericArgument::Type(model_type)) = inner_args.args.first() {
                    return Some(model_type.clone());
                }
            }
        }
    }
    Some(inner.clone())
}
