use crate::{
    data::{MappingData, StructuredNote},
    input_form::StructuredInputForm,
    midi::MidiCommand,
};
use crossterm::event::KeyCode;
use kanal::Sender;
use ratatui::widgets::ListState;
use serde_json;
use std::{collections::HashMap, error::Error, fs};

#[derive(Debug, PartialEq)]
pub enum InputMode {
    Normal,
    EditValue,
    SaveFile,
    LoadFile,
    StructuredInput,
}

#[derive(Debug, PartialEq, Clone, Copy)]
pub enum SelectedRegister {
    IC03,
    IC10,
    IC11,
}

impl SelectedRegister {
    pub fn as_str(&self) -> &str {
        match self {
            SelectedRegister::IC03 => "IC03",
            SelectedRegister::IC10 => "IC10",
            SelectedRegister::IC11 => "IC11",
        }
    }

    pub fn cc_pair(&self) -> (u8, u8) {
        match self {
            SelectedRegister::IC03 => (20, 21),
            SelectedRegister::IC10 => (22, 23),
            SelectedRegister::IC11 => (24, 25),
        }
    }
}

pub struct App {
    pub structured_notes: Vec<StructuredNote>,
    pub register_values: HashMap<String, u8>,
    pub selected_register: SelectedRegister,
    pub input_mode: InputMode,
    pub input_buffer: String,
    pub cursor_position: usize,
    pub notes_list_state: ListState,
    pub command_sender: Sender<MidiCommand>,
    pub status_message: String,
    pub show_help: bool,
    pub structured_form: StructuredInputForm,
}

impl App {
    pub fn new(command_sender: Sender<MidiCommand>) -> Self {
        let register_values = {
            let mut map = HashMap::new();
            map.insert("IC03".to_string(), 255);
            map.insert("IC10".to_string(), 255);
            map.insert("IC11".to_string(), 8);
            map
        };

        let structured_form = StructuredInputForm::new(register_values.clone());

        Self {
            structured_notes: Vec::new(),
            register_values,
            selected_register: SelectedRegister::IC03,
            input_mode: InputMode::Normal,
            input_buffer: String::new(),
            cursor_position: 0,
            notes_list_state: ListState::default(),
            command_sender,
            status_message: "Ready - Press 'n' for new note, ←→ for registers, 'h' for help"
                .to_string(),
            show_help: false,
            structured_form,
        }
    }

    pub fn add_structured_note(&mut self) {
        let note = self.structured_form.finalize_note();

        // Check if a note already exists for this register state
        let current_values = self.register_values.clone();

        if let Some(existing_note) = self
            .structured_notes
            .iter_mut()
            .find(|n| n.register_values == current_values)
        {
            *existing_note = note;
            self.status_message = "Note updated".to_string();
        } else {
            self.structured_notes.push(note);
            self.status_message = "Note added".to_string();
        }
    }

    pub fn start_structured_input(&mut self) {
        self.structured_form.reset(self.register_values.clone());

        // Check if a note already exists for this register state and pre-load it
        let current_values = self.register_values.clone();
        if let Some(existing_note) = self
            .structured_notes
            .iter()
            .find(|n| n.register_values == current_values)
        {
            self.structured_form.current_note = existing_note.clone();
        }

        self.input_mode = InputMode::StructuredInput;
    }

    pub fn get_current_value(&self) -> u8 {
        *self
            .register_values
            .get(self.selected_register.as_str())
            .unwrap_or(&0)
    }

    pub fn set_current_value(&mut self, value: u8) {
        self.register_values
            .insert(self.selected_register.as_str().to_string(), value);
        self.send_midi_value(value);
    }

    pub fn send_midi_value(&self, value: u8) {
        let (cc_low, cc_high) = self.selected_register.cc_pair();

        if value <= 127 {
            let _ = self
                .command_sender
                .send(MidiCommand::ControlChange { cc: cc_low, value });
        } else {
            let _ = self.command_sender.send(MidiCommand::ControlChange {
                cc: cc_high,
                value: value - 128,
            });
        }
    }

    pub fn toggle_bit(&mut self, bit: u8) {
        let current = self.get_current_value();
        let mask = 1 << bit;
        let new_value = current ^ mask;
        self.set_current_value(new_value);
        self.status_message = format!(
            "Toggled {}:bit{} ({})",
            self.selected_register.as_str(),
            bit,
            new_value
        );
    }

    pub fn save_mapping(&self, filename: &str) -> Result<(), Box<dyn Error>> {
        // Convert structured notes to legacy format for saving
        let legacy_data = MappingData::from_structured_notes(
            self.structured_notes.clone(),
            self.register_values.clone(),
        );
        let json = serde_json::to_string_pretty(&legacy_data)?;
        fs::write(filename, json)?;
        Ok(())
    }

    pub fn load_mapping(&mut self, filename: &str) -> Result<(), Box<dyn Error>> {
        let content = fs::read_to_string(filename)?;
        let legacy_data: MappingData = serde_json::from_str(&content)?;

        // Convert legacy format to structured notes for editing
        self.structured_notes = legacy_data.to_structured_notes();
        self.register_values = legacy_data.register_values.clone();

        // Send current register values to hardware
        for (register, &value) in &legacy_data.register_values {
            match register.as_str() {
                "IC03" => {
                    let old_selected = self.selected_register;
                    self.selected_register = SelectedRegister::IC03;
                    self.send_midi_value(value);
                    self.selected_register = old_selected;
                }
                "IC10" => {
                    let old_selected = self.selected_register;
                    self.selected_register = SelectedRegister::IC10;
                    self.send_midi_value(value);
                    self.selected_register = old_selected;
                }
                "IC11" => {
                    let old_selected = self.selected_register;
                    self.selected_register = SelectedRegister::IC11;
                    self.send_midi_value(value);
                    self.selected_register = old_selected;
                }
                _ => {}
            }
        }

        Ok(())
    }

    pub fn handle_structured_input(&mut self, key: KeyCode) -> Result<bool, Box<dyn Error>> {
        match key {
            KeyCode::Enter => {
                if !self.structured_form.current_note.is_empty() {
                    self.add_structured_note();
                }
                self.input_mode = InputMode::Normal;
            }
            KeyCode::Esc => {
                self.input_mode = InputMode::Normal;
            }
            KeyCode::Char(' ') => {
                let next_field = self.structured_form.current_field.next();
                let text_len = self.structured_form.get_text_value(&next_field).len();
                self.structured_form.current_field = next_field;
                self.structured_form.cursor_position = text_len;
            }
            KeyCode::Up => {
                let prev_field = self.structured_form.current_field.prev();
                let text_len = self.structured_form.get_text_value(&prev_field).len();
                self.structured_form.current_field = prev_field;
                self.structured_form.cursor_position = text_len;
            }
            KeyCode::Down => {
                let next_field = self.structured_form.current_field.next();
                let text_len = self.structured_form.get_text_value(&next_field).len();
                self.structured_form.current_field = next_field;
                self.structured_form.cursor_position = text_len;
            }
            _ => {
                if self.structured_form.current_field.is_led_field() {
                    self.handle_led_input(key);
                } else if self.structured_form.current_field.is_text_field() {
                    self.handle_text_input(key);
                }
            }
        }
        Ok(false)
    }

    fn handle_led_input(&mut self, key: KeyCode) {
        if let KeyCode::Char(c) = key {
            if c == '0' || c == '1' {
                let value = if c == '1' { Some(1) } else { Some(0) };
                let current_field = self.structured_form.current_field;
                self.structured_form.set_led_value(&current_field, value);
                // Auto-advance to next field
                self.structured_form.current_field = self.structured_form.current_field.next();
            }
        }
    }

    fn handle_text_input(&mut self, key: KeyCode) {
        let current_field = self.structured_form.current_field;
        let cursor_pos = self.structured_form.cursor_position;

        if let Some(current_text) = self.structured_form.get_text_value_mut(&current_field) {
            match key {
                KeyCode::Char(c) => {
                    current_text.insert(cursor_pos, c);
                }
                KeyCode::Backspace => {
                    if cursor_pos > 0 {
                        current_text.remove(cursor_pos - 1);
                    }
                }
                KeyCode::Delete => {
                    if cursor_pos < current_text.len() {
                        current_text.remove(cursor_pos);
                    }
                }
                _ => {}
            }
        }

        // Update cursor position after text operations
        match key {
            KeyCode::Char(_) => {
                self.structured_form.cursor_position += 1;
            }
            KeyCode::Backspace => {
                if cursor_pos > 0 {
                    self.structured_form.cursor_position -= 1;
                }
            }
            KeyCode::Left => {
                if cursor_pos > 0 {
                    self.structured_form.cursor_position -= 1;
                }
            }
            KeyCode::Right => {
                let text_len = self.structured_form.get_text_value(&current_field).len();
                if cursor_pos < text_len {
                    self.structured_form.cursor_position += 1;
                }
            }
            KeyCode::Home => {
                self.structured_form.cursor_position = 0;
            }
            KeyCode::End => {
                let text_len = self.structured_form.get_text_value(&current_field).len();
                self.structured_form.cursor_position = text_len;
            }
            _ => {}
        }
    }
}
