// src/tui/functions/common/register.rs

use crate::services::auth::AuthClient;
use crate::state::{
    pages::auth::RegisterState,
    app::state::AppState,
};
use crate::ui::handlers::context::DialogPurpose;
use crate::state::app::buffer::{AppView, BufferState};
use common::proto::komp_ac::auth::AuthResponse;
use canvas::canvas::CanvasState;
use anyhow::Context;
use tokio::spawn;
use tokio::sync::mpsc;
use tracing::{info, error};

#[derive(Debug)]
pub enum RegisterResult {
    Success(AuthResponse),
    Failure(String),
    ConnectionError(String),
}

/// Clears the registration form fields.
pub async fn revert(
    register_state: &mut RegisterState,
    _app_state: &mut AppState, // Keep signature consistent if needed elsewhere
) -> String {
    register_state.username.clear();
    register_state.email.clear();
    register_state.password.clear();
    register_state.password_confirmation.clear();
    register_state.role.clear();
    register_state.error_message = None;
    register_state.set_has_unsaved_changes(false);
    register_state.current_field = 0; // Reset focus to first field
    register_state.current_cursor_pos = 0;
    "Registration form cleared".to_string()
}

/// Clears the form and returns to the intro screen.
pub async fn back_to_login(
    register_state: &mut RegisterState,
    app_state: &mut AppState,
    buffer_state: &mut BufferState,
) -> String {
    // Clear fields first
    let _ = revert(register_state, app_state).await;

    // Ensure dialog is hidden
    app_state.hide_dialog();

    // Navigation logic
    buffer_state.close_active_buffer();
    buffer_state.update_history(AppView::Login);

    // Reset focus state
    app_state.ui.focus_outside_canvas = false;
    app_state.focused_button_index = 0;

    "Returned to main menu".to_string()
}

/// Validates input, shows loading, and spawns the registration task.
pub fn initiate_registration(
    register_state: &RegisterState,
    app_state: &mut AppState,
    mut auth_client: AuthClient,
    sender: mpsc::Sender<RegisterResult>,
) -> String {
    // Clone necessary data
    let username = register_state.username.clone();
    let email = register_state.email.clone();
    let password = register_state.password.clone();
    let password_confirmation = register_state.password_confirmation.clone();
    let role = register_state.role.clone();

    // 1. Client-side validation
    if username.trim().is_empty() {
        app_state.show_dialog("Registration Failed", "Username cannot be empty.", vec!["OK".to_string()], DialogPurpose::RegisterFailed);
        "Username cannot be empty.".to_string()
    } else if !password.is_empty() && password != password_confirmation {
         app_state.show_dialog("Registration Failed", "Passwords do not match.", vec!["OK".to_string()], DialogPurpose::RegisterFailed);
         "Passwords do not match.".to_string()
    } else {
        // 2. Show Loading Dialog
        app_state.show_loading_dialog("Registering", "Please wait...");

        // 3. Spawn the registration task
        spawn(async move {
            let password_opt = if password.is_empty() { None } else { Some(password) };
            let password_conf_opt = if password_confirmation.is_empty() { None } else { Some(password_confirmation) };
            let role_opt = if role.is_empty() { None } else { Some(role) };
            let register_outcome = match auth_client.register(username.clone(), email, password_opt, password_conf_opt, role_opt).await
                .with_context(|| format!("Spawned register task failed for username: {}", username))
            {
                Ok(response) => RegisterResult::Success(response),
                Err(e) => RegisterResult::Failure(format!("{}", e)),
            };
            // Send result back to the main UI thread
            if let Err(e) = sender.send(register_outcome).await {
                error!("Failed to send registration result: {}", e);
            }
        });

        // 4. Return immediately
        "Registration initiated.".to_string()
    }
}

/// Handles the result received from the registration task.
/// Returns true if a redraw is needed.
pub fn handle_registration_result(
    result: RegisterResult,
    app_state: &mut AppState,
    register_state: &mut RegisterState,
) -> bool {
    match result {
        RegisterResult::Success(response) => {
            let success_message = format!(
                "Registration Successful!\n\nUser ID: {}\nUsername: {}\nEmail: {}\nRole: {}",
                response.id, response.username, response.email, response.role
            );
            app_state.update_dialog_content(
                &success_message,
                vec!["OK".to_string()],
                DialogPurpose::RegisterSuccess,
            );
            info!(message = %success_message, "Registration successful");
        }
        RegisterResult::Failure(err_msg) | RegisterResult::ConnectionError(err_msg) => {
            app_state.update_dialog_content(
                &err_msg,
                vec!["OK".to_string()],
                DialogPurpose::RegisterFailed,
            );
            register_state.error_message = Some(err_msg.clone());
            error!(error = %err_msg, "Registration failed/connection error");
        }
    }
    register_state.set_has_unsaved_changes(false); // Clear flag after processing
    true // Request redraw as dialog content changed
}
