// src/pages/register/state.rs

use canvas::{DataProvider, AppMode, FormEditor};
use std::fmt;

use crossterm::event::{KeyCode, KeyEvent, KeyModifiers};
use canvas::keymap::KeyEventOutcome;
use crate::pages::register::suggestions::role_suggestions_sync;

/// Represents the state of the Registration form UI
#[derive(Debug, Clone)]
pub struct RegisterState {
    pub username: String,
    pub email: String,
    pub password: String,
    pub password_confirmation: String,
    pub role: String,
    pub error_message: Option<String>,
    pub current_field: usize,
    pub current_cursor_pos: usize,
    pub has_unsaved_changes: bool,
    pub app_mode: canvas::AppMode,
}

impl Default for RegisterState {
    fn default() -> Self {
        Self {
            username: String::new(),
            email: String::new(),
            password: String::new(),
            password_confirmation: String::new(),
            role: String::new(),
            error_message: None,
            current_field: 0,
            current_cursor_pos: 0,
            has_unsaved_changes: false,
            app_mode: canvas::AppMode::Edit,
        }
    }
}

impl RegisterState {
    pub fn new() -> Self {
        Self {
            app_mode: canvas::AppMode::Edit,
            ..Default::default()
        }
    }

    pub fn current_field(&self) -> usize {
        self.current_field
    }

    pub fn current_cursor_pos(&self) -> usize {
        self.current_cursor_pos
    }

    pub fn set_current_field(&mut self, index: usize) {
        if index < 5 {
            self.current_field = index;
        }
    }

    pub fn set_current_cursor_pos(&mut self, pos: usize) {
        self.current_cursor_pos = pos;
    }

    pub fn get_current_input(&self) -> &str {
        match self.current_field {
            0 => &self.username,
            1 => &self.email,
            2 => &self.password,
            3 => &self.password_confirmation,
            4 => &self.role,
            _ => "",
        }
    }

    pub fn get_current_input_mut(&mut self, index: usize) -> &mut String {
        match index {
            0 => &mut self.username,
            1 => &mut self.email,
            2 => &mut self.password,
            3 => &mut self.password_confirmation,
            4 => &mut self.role,
            _ => panic!("Invalid current_field index in RegisterState"),
        }
    }

    pub fn current_mode(&self) -> AppMode {
        self.app_mode
    }

    pub fn has_unsaved_changes(&self) -> bool {
        self.has_unsaved_changes
    }

    pub fn set_has_unsaved_changes(&mut self, changed: bool) {
        self.has_unsaved_changes = changed;
    }
}

impl DataProvider for RegisterState {
    fn field_count(&self) -> usize { 5 }

    fn field_name(&self, index: usize) -> &str {
        match index {
            0 => "Username",
            1 => "Email (Optional)",
            2 => "Password (Optional)",
            3 => "Confirm Password",
            4 => "Role (Optional)",
            _ => "",
        }
    }

    fn field_value(&self, index: usize) -> &str {
        match index {
            0 => &self.username,
            1 => &self.email,
            2 => &self.password,
            3 => &self.password_confirmation,
            4 => &self.role,
            _ => "",
        }
    }

    fn set_field_value(&mut self, index: usize, value: String) {
        match index {
            0 => self.username = value,
            1 => self.email = value,
            2 => self.password = value,
            3 => self.password_confirmation = value,
            4 => self.role = value,
            _ => {}
        }
        self.has_unsaved_changes = true;
    }

    fn supports_suggestions(&self, field_index: usize) -> bool {
        field_index == 4 // only Role field supports suggestions
    }
}

/// Wrapper that owns both the raw register state and its editor
pub struct RegisterFormState {
    pub state: RegisterState,
    pub editor: FormEditor<RegisterState>,
}

impl Default for RegisterFormState {
    fn default() -> Self {
        Self::new()
    }
}

// manual Debug because FormEditor doesn’t implement Debug
impl fmt::Debug for RegisterFormState {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("RegisterFormState")
            .field("state", &self.state)
            .finish()
    }
}

impl RegisterFormState {
    /// Sync the editor's data provider back into our state
    pub fn sync_from_editor(&mut self) {
        // The FormEditor holds the authoritative data
        let dp = self.editor.data_provider();
        self.state = dp.clone(); // because RegisterState: Clone
    }

    pub fn new() -> Self {
        let state = RegisterState::default();
        let editor = FormEditor::new(state.clone());
        Self { state, editor }
    }

    // === Delegates to RegisterState ===
    pub fn username(&self) -> &str {
        &self.state.username
    }
    pub fn username_mut(&mut self) -> &mut String {
        &mut self.state.username
    }

    pub fn email(&self) -> &str {
        &self.state.email
    }
    pub fn email_mut(&mut self) -> &mut String {
        &mut self.state.email
    }

    pub fn password(&self) -> &str {
        &self.state.password
    }
    pub fn password_mut(&mut self) -> &mut String {
        &mut self.state.password
    }

    pub fn password_confirmation(&self) -> &str {
        &self.state.password_confirmation
    }
    pub fn password_confirmation_mut(&mut self) -> &mut String {
        &mut self.state.password_confirmation
    }

    pub fn role(&self) -> &str {
        &self.state.role
    }
    pub fn role_mut(&mut self) -> &mut String {
        &mut self.state.role
    }

    pub fn error_message(&self) -> Option<&String> {
        self.state.error_message.as_ref()
    }
    pub fn set_error_message(&mut self, msg: Option<String>) {
        self.state.error_message = msg;
    }

    pub fn has_unsaved_changes(&self) -> bool {
        self.state.has_unsaved_changes
    }
    pub fn set_has_unsaved_changes(&mut self, changed: bool) {
        self.state.has_unsaved_changes = changed;
    }

    pub fn clear(&mut self) {
        self.state.username.clear();
        self.state.email.clear();
        self.state.password.clear();
        self.state.password_confirmation.clear();
        self.state.role.clear();
        self.state.error_message = None;
        self.state.has_unsaved_changes = false;
        self.state.current_field = 0;
        self.state.current_cursor_pos = 0;
    }

    // === Delegates to cursor/input ===
    pub fn current_field(&self) -> usize {
        self.state.current_field()
    }
    pub fn set_current_field(&mut self, index: usize) {
        self.state.set_current_field(index);
    }
    pub fn current_cursor_pos(&self) -> usize {
        self.state.current_cursor_pos()
    }
    pub fn set_current_cursor_pos(&mut self, pos: usize) {
        self.state.set_current_cursor_pos(pos);
    }
    pub fn get_current_input(&self) -> &str {
        self.state.get_current_input()
    }
    pub fn get_current_input_mut(&mut self) -> &mut String {
        self.state.get_current_input_mut(self.state.current_field)
    }

    // === Delegates to FormEditor ===
    pub fn mode(&self) -> canvas::AppMode {
        self.editor.mode()
    }
    pub fn cursor_position(&self) -> usize {
        self.editor.cursor_position()
    }

    pub fn handle_key_event(
        &mut self,
        key_event: crossterm::event::KeyEvent,
    ) -> canvas::keymap::KeyEventOutcome {
        // Only customize behavior for the Role field (index 4) in Edit mode
        let in_role_field = self.editor.current_field() == 4;
        let in_edit_mode = self.editor.mode() == canvas::AppMode::Edit;

        if in_role_field && in_edit_mode {
            match key_event.code {
                // Tab: open suggestions if inactive; otherwise cycle next
                KeyCode::Tab => {
                    if !self.editor.is_suggestions_active() {
                        if let Some(query) = self.editor.start_suggestions(4) {
                            let items = role_suggestions_sync(&query);
                            let applied =
                                self.editor.apply_suggestions_result(4, &query, items);
                            if applied {
                                self.editor.update_inline_completion();
                            }
                        }
                    } else {
                        // Cycle to next suggestion
                        self.editor.suggestions_next();
                    }
                    return KeyEventOutcome::Consumed(None);
                }

                // Shift+Tab (BackTab): cycle suggestions too (fallback to next)
                KeyCode::BackTab => {
                    if self.editor.is_suggestions_active() {
                        // If your canvas exposes suggestions_prev(), use it here.
                        // Fallback: cycle next.
                        self.editor.suggestions_next();
                        return KeyEventOutcome::Consumed(None);
                    }
                }

                // Enter: if suggestions active — apply selected suggestion
                KeyCode::Enter => {
                    if self.editor.is_suggestions_active() {
                        let _ = self.editor.apply_suggestion();
                        return KeyEventOutcome::Consumed(None);
                    }
                }

                // Esc: close suggestions if active
                KeyCode::Esc => {
                    if self.editor.is_suggestions_active() {
                        self.editor.close_suggestions();
                        return KeyEventOutcome::Consumed(None);
                    }
                }

                // Character input: first let editor mutate text, then refilter if active
                KeyCode::Char(_) => {
                    let outcome = self.editor.handle_key_event(key_event);
                    if self.editor.is_suggestions_active() {
                        if let Some(query) = self.editor.start_suggestions(4) {
                            let items = role_suggestions_sync(&query);
                            let applied =
                                self.editor.apply_suggestions_result(4, &query, items);
                            if applied {
                                self.editor.update_inline_completion();
                            }
                        }
                    }
                    return outcome;
                }

                // Backspace/Delete: mutate then refilter if active
                KeyCode::Backspace | KeyCode::Delete => {
                    let outcome = self.editor.handle_key_event(key_event);
                    if self.editor.is_suggestions_active() {
                        if let Some(query) = self.editor.start_suggestions(4) {
                            let items = role_suggestions_sync(&query);
                            let applied =
                                self.editor.apply_suggestions_result(4, &query, items);
                            if applied {
                                self.editor.update_inline_completion();
                            }
                        }
                    }
                    return outcome;
                }

                _ => { /* fall through to default */ }
            }
        }

        // Default: let canvas handle it
        self.editor.handle_key_event(key_event)
    }
}
