// src/tui/functions/common/form.rs

use crate::services::grpc_client::GrpcClient;
use crate::state::app::state::AppState; // NEW: Import AppState
use crate::state::pages::form::FormState;
use crate::utils::data_converter; // NEW: Import our translator
use anyhow::{anyhow, Context, Result};
use std::collections::HashMap;

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum SaveOutcome {
    NoChange,
    UpdatedExisting,
    CreatedNew(i64),
}

// MODIFIED save function signature and logic
pub async fn save(
    app_state: &AppState, // NEW: Pass in AppState
    form_state: &mut FormState,
    grpc_client: &mut GrpcClient,
) -> Result<SaveOutcome> {
    if !form_state.has_unsaved_changes {
        return Ok(SaveOutcome::NoChange);
    }

    // --- NEW: VALIDATION & CONVERSION STEP ---
    let cache_key =
        format!("{}.{}", form_state.profile_name, form_state.table_name);
    let schema = match app_state.schema_cache.get(&cache_key) {
        Some(s) => s,
        None => {
            return Err(anyhow!(
                "Schema for table '{}' not found in cache. Cannot save.",
                form_state.table_name
            ));
        }
    };

    let data_map: HashMap<String, String> = form_state
        .fields
        .iter()
        .zip(form_state.values.iter())
        .map(|(field_def, value)| (field_def.data_key.clone(), value.clone()))
        .collect();

    // Use our new translator. It returns a user-friendly error on failure.
    let converted_data =
        match data_converter::convert_and_validate_data(&data_map, schema) {
            Ok(data) => data,
            Err(user_error) => return Err(anyhow!(user_error)),
        };
    // --- END OF NEW STEP ---

    let outcome: SaveOutcome;
    let is_new_entry = form_state.id == 0
        || (form_state.total_count > 0
            && form_state.current_position > form_state.total_count)
        || (form_state.total_count == 0 && form_state.current_position == 1);

    if is_new_entry {
        let response = grpc_client
            .post_table_data(
                form_state.profile_name.clone(),
                form_state.table_name.clone(),
                converted_data, // Use the validated & converted data
            )
            .await
            .context("Failed to post new table data")?;

        if response.success {
            form_state.id = response.inserted_id;
            form_state.total_count += 1;
            form_state.current_position = form_state.total_count;
            outcome = SaveOutcome::CreatedNew(response.inserted_id);
        } else {
            return Err(anyhow!(
                "Server failed to insert data: {}",
                response.message
            ));
        }
    } else {
        if form_state.id == 0 {
            return Err(anyhow!(
                "Cannot update record: ID is 0, but not classified as new entry."
            ));
        }
        let response = grpc_client
            .put_table_data(
                form_state.profile_name.clone(),
                form_state.table_name.clone(),
                form_state.id,
                converted_data, // Use the validated & converted data
            )
            .await
            .context("Failed to put (update) table data")?;

        if response.success {
            outcome = SaveOutcome::UpdatedExisting;
        } else {
            return Err(anyhow!(
                "Server failed to update data: {}",
                response.message
            ));
        }
    }

    form_state.has_unsaved_changes = false;
    Ok(outcome)
}

pub async fn revert(
    form_state: &mut FormState, // Takes &mut FormState to update it
    grpc_client: &mut GrpcClient,
) -> Result<String> {
    if form_state.id == 0 || (form_state.total_count > 0 && form_state.current_position > form_state.total_count) || (form_state.total_count == 0 && form_state.current_position == 1) {
        let old_total_count = form_state.total_count; // Preserve for correct new position
        form_state.reset_to_empty(); // reset_to_empty will clear values and set id=0
        form_state.total_count = old_total_count; // Restore total_count
        if form_state.total_count > 0 { // Correctly set current_position for new
             form_state.current_position = form_state.total_count + 1;
        } else {
             form_state.current_position = 1;
        }
        return Ok("New entry cleared".to_string());
    }

    if form_state.current_position == 0 || form_state.current_position > form_state.total_count {
        if form_state.total_count > 0 {
            form_state.current_position = 1;
        } else {
            // No records to revert to, effectively a new entry state.
            form_state.reset_to_empty();
            return Ok("No saved data to revert to; form cleared.".to_string());
        }
    }

    let response = grpc_client
        .get_table_data_by_position(
            form_state.profile_name.clone(),
            form_state.table_name.clone(),
            form_state.current_position as i32,
        )
        .await
        .context(format!(
            "Failed to get table data by position {} for table {}.{}",
            form_state.current_position,
            form_state.profile_name,
            form_state.table_name
        ))?;

    // FIX: Pass the current position as the second argument
    form_state.update_from_response(&response.data, form_state.current_position);
    Ok("Changes discarded, reloaded last saved version".to_string())
}

