// src/utils/data_converter.rs

use common::proto::komp_ac::table_structure::TableStructureResponse;
use prost_types::{value::Kind, NullValue, Value};
use std::collections::HashMap;

pub fn convert_and_validate_data(
    data: &HashMap<String, String>,
    schema: &TableStructureResponse,
) -> Result<HashMap<String, Value>, String> {
    let type_map: HashMap<_, _> = schema
        .columns
        .iter()
        .map(|col| (col.name.as_str(), col.data_type.as_str()))
        .collect();

    data.iter()
        .map(|(key, str_value)| {
            let expected_type = type_map.get(key.as_str()).unwrap_or(&"TEXT");

            let kind = if str_value.is_empty() {
                // TODO: Use the correct enum variant
                Kind::NullValue(NullValue::NullValue.into())
            } else {
                // Attempt to parse the string based on the expected type
                match *expected_type {
                    "BOOL" => match str_value.to_lowercase().parse::<bool>() {
                        Ok(v) => Kind::BoolValue(v),
                        Err(_) => return Err(format!("Invalid boolean for '{}': must be 'true' or 'false'", key)),
                    },
                    "INT8" | "INT4" | "INT2" | "SERIAL" | "BIGSERIAL" => {
                        match str_value.parse::<f64>() {
                            Ok(v) => Kind::NumberValue(v),
                            Err(_) => return Err(format!("Invalid number for '{}': must be a whole number", key)),
                        }
                    }
                    "NUMERIC" | "FLOAT4" | "FLOAT8" => match str_value.parse::<f64>() {
                        Ok(v) => Kind::NumberValue(v),
                        Err(_) => return Err(format!("Invalid decimal for '{}': must be a number", key)),
                    },
                    "TIMESTAMPTZ" | "DATE" | "TIME" | "TEXT" | "VARCHAR" | "UUID" => {
                        Kind::StringValue(str_value.clone())
                    }
                    _ => Kind::StringValue(str_value.clone()),
                }
            };
            Ok((key.clone(), Value { kind: Some(kind) }))
        })
        .collect()
}
