use crossterm::event::{KeyCode, KeyEvent, KeyModifiers};
use std::sync::atomic::Ordering;

use super::{InputContext, InputResult};
use crate::commands::AppCommand;
use crate::state::{ConfirmAction, Modal, PatternsColumn, RenameTarget};

pub(super) fn handle_patterns_page(ctx: &mut InputContext, key: KeyEvent) -> InputResult {
    let ctrl = key.modifiers.contains(KeyModifiers::CONTROL);
    let shift = key.modifiers.contains(KeyModifiers::SHIFT);
    let alt = key.modifiers.contains(KeyModifiers::ALT);

    match key.code {
        KeyCode::Up if alt && ctx.app.patterns_nav.column == PatternsColumn::Patterns => {
            ctx.dispatch(AppCommand::ShiftPatternsUp);
        }
        KeyCode::Down if alt && ctx.app.patterns_nav.column == PatternsColumn::Patterns => {
            ctx.dispatch(AppCommand::ShiftPatternsDown);
        }
        KeyCode::Up if shift => {
            match ctx.app.patterns_nav.column {
                PatternsColumn::Banks => {
                    if ctx.app.patterns_nav.bank_anchor.is_none() {
                        ctx.app.patterns_nav.bank_anchor = Some(ctx.app.patterns_nav.bank_cursor);
                    }
                }
                PatternsColumn::Patterns => {
                    if ctx.app.patterns_nav.pattern_anchor.is_none() {
                        ctx.app.patterns_nav.pattern_anchor =
                            Some(ctx.app.patterns_nav.pattern_cursor);
                    }
                }
            }
            ctx.app.patterns_nav.move_up_clamped();
        }
        KeyCode::Down if shift => {
            match ctx.app.patterns_nav.column {
                PatternsColumn::Banks => {
                    if ctx.app.patterns_nav.bank_anchor.is_none() {
                        ctx.app.patterns_nav.bank_anchor = Some(ctx.app.patterns_nav.bank_cursor);
                    }
                }
                PatternsColumn::Patterns => {
                    if ctx.app.patterns_nav.pattern_anchor.is_none() {
                        ctx.app.patterns_nav.pattern_anchor =
                            Some(ctx.app.patterns_nav.pattern_cursor);
                    }
                }
            }
            ctx.app.patterns_nav.move_down_clamped();
        }
        KeyCode::Up => {
            ctx.app.patterns_nav.clear_selection();
            ctx.dispatch(AppCommand::PatternsCursorUp);
        }
        KeyCode::Down => {
            ctx.app.patterns_nav.clear_selection();
            ctx.dispatch(AppCommand::PatternsCursorDown);
        }
        KeyCode::Left => ctx.dispatch(AppCommand::PatternsCursorLeft),
        KeyCode::Right => ctx.dispatch(AppCommand::PatternsCursorRight),
        KeyCode::Esc => {
            if ctx.app.patterns_nav.has_selection() {
                ctx.app.patterns_nav.clear_selection();
            } else if !ctx.app.playback.staged_changes.is_empty()
                || !ctx.app.playback.staged_mute_changes.is_empty()
                || !ctx.app.playback.staged_prop_changes.is_empty()
            {
                ctx.dispatch(AppCommand::ClearStagedChanges);
            } else {
                ctx.dispatch(AppCommand::PatternsBack);
            }
        }
        KeyCode::Enter => {
            if !ctx.app.patterns_nav.has_selection() {
                ctx.dispatch(AppCommand::PatternsEnter);
            }
        }
        KeyCode::Char('p') => {
            if ctx.app.patterns_nav.column == PatternsColumn::Patterns {
                let bank = ctx.app.patterns_nav.bank_cursor;
                for pattern in ctx.app.patterns_nav.selected_patterns() {
                    ctx.app.stage_pattern_toggle(bank, pattern, ctx.snapshot);
                }
            }
        }
        KeyCode::Char(' ') if !ctx.app.plugin_mode => {
            ctx.dispatch(AppCommand::TogglePlaying);
            ctx.playing
                .store(ctx.app.playback.playing, Ordering::Relaxed);
        }
        KeyCode::Char('c') if !ctrl => {
            let mute_changed = ctx.app.commit_staged_changes();
            if mute_changed {
                ctx.app.send_mute_state(ctx.seq_cmd_tx);
            }
        }
        KeyCode::Char('q') if !ctx.app.plugin_mode => {
            ctx.dispatch(AppCommand::OpenModal(Modal::Confirm {
                action: ConfirmAction::Quit,
                selected: false,
            }));
        }
        KeyCode::Char('z') if ctrl && !shift => {
            ctx.dispatch(AppCommand::Undo);
        }
        KeyCode::Char('Z') if ctrl => {
            ctx.dispatch(AppCommand::Redo);
        }
        KeyCode::Char('c') if ctrl => {
            let bank = ctx.app.patterns_nav.bank_cursor;
            match ctx.app.patterns_nav.column {
                PatternsColumn::Banks => {
                    let banks = ctx.app.patterns_nav.selected_banks();
                    if banks.len() > 1 {
                        ctx.dispatch(AppCommand::CopyBanks { banks });
                    } else {
                        ctx.dispatch(AppCommand::CopyBank { bank });
                    }
                }
                PatternsColumn::Patterns => {
                    let patterns = ctx.app.patterns_nav.selected_patterns();
                    if patterns.len() > 1 {
                        ctx.dispatch(AppCommand::CopyPatterns { bank, patterns });
                    } else {
                        let pattern = ctx.app.patterns_nav.pattern_cursor;
                        ctx.dispatch(AppCommand::CopyPattern { bank, pattern });
                    }
                }
            }
        }
        KeyCode::Char('v') if ctrl => {
            let bank = ctx.app.patterns_nav.bank_cursor;
            match ctx.app.patterns_nav.column {
                PatternsColumn::Banks => {
                    if ctx.app.copied_banks.as_ref().is_some_and(|v| v.len() > 1) {
                        ctx.dispatch(AppCommand::PasteBanks { start: bank });
                    } else {
                        ctx.dispatch(AppCommand::PasteBank { bank });
                    }
                }
                PatternsColumn::Patterns => {
                    let pattern = ctx.app.patterns_nav.pattern_cursor;
                    if ctx
                        .app
                        .copied_patterns
                        .as_ref()
                        .is_some_and(|v| v.len() > 1)
                    {
                        ctx.dispatch(AppCommand::PastePatterns {
                            bank,
                            start: pattern,
                        });
                    } else {
                        ctx.dispatch(AppCommand::PastePattern { bank, pattern });
                    }
                }
            }
        }
        KeyCode::Delete | KeyCode::Backspace => {
            let bank = ctx.app.patterns_nav.bank_cursor;
            match ctx.app.patterns_nav.column {
                PatternsColumn::Banks => {
                    let banks = ctx.app.patterns_nav.selected_banks();
                    if banks.len() > 1 {
                        ctx.dispatch(AppCommand::OpenModal(Modal::Confirm {
                            action: ConfirmAction::ResetBanks { banks },
                            selected: false,
                        }));
                    } else {
                        ctx.dispatch(AppCommand::OpenModal(Modal::Confirm {
                            action: ConfirmAction::ResetBank { bank },
                            selected: false,
                        }));
                    }
                }
                PatternsColumn::Patterns => {
                    let patterns = ctx.app.patterns_nav.selected_patterns();
                    if patterns.len() > 1 {
                        ctx.dispatch(AppCommand::OpenModal(Modal::Confirm {
                            action: ConfirmAction::ResetPatterns { bank, patterns },
                            selected: false,
                        }));
                    } else {
                        let pattern = ctx.app.patterns_nav.pattern_cursor;
                        ctx.dispatch(AppCommand::OpenModal(Modal::Confirm {
                            action: ConfirmAction::ResetPattern { bank, pattern },
                            selected: false,
                        }));
                    }
                }
            }
        }
        KeyCode::Char('r') => {
            if !ctx.app.patterns_nav.has_selection() {
                let bank = ctx.app.patterns_nav.bank_cursor;
                match ctx.app.patterns_nav.column {
                    PatternsColumn::Banks => {
                        let current_name = ctx.app.project_state.project.banks[bank]
                            .name
                            .clone()
                            .unwrap_or_default();
                        ctx.dispatch(AppCommand::OpenModal(Modal::Rename {
                            target: RenameTarget::Bank { bank },
                            name: current_name,
                        }));
                    }
                    PatternsColumn::Patterns => {
                        let pattern = ctx.app.patterns_nav.pattern_cursor;
                        let current_name = ctx.app.project_state.project.banks[bank].patterns
                            [pattern]
                            .name
                            .clone()
                            .unwrap_or_default();
                        ctx.dispatch(AppCommand::OpenModal(Modal::Rename {
                            target: RenameTarget::Pattern { bank, pattern },
                            name: current_name,
                        }));
                    }
                }
            }
        }
        KeyCode::Char('e') if !ctrl => {
            if ctx.app.patterns_nav.column == PatternsColumn::Patterns
                && !ctx.app.patterns_nav.has_selection()
            {
                let bank = ctx.app.patterns_nav.bank_cursor;
                let pattern = ctx.app.patterns_nav.pattern_cursor;
                ctx.dispatch(AppCommand::OpenPatternPropsModal { bank, pattern });
            }
        }
        KeyCode::Char('d') => {
            if ctx.app.patterns_nav.column == PatternsColumn::Patterns
                && !ctx.app.patterns_nav.has_selection()
            {
                let bank = ctx.app.patterns_nav.bank_cursor;
                let pattern = ctx.app.patterns_nav.pattern_cursor;
                let current_desc = ctx.app.project_state.project.banks[bank].patterns[pattern]
                    .description
                    .clone()
                    .unwrap_or_default();
                ctx.dispatch(AppCommand::OpenModal(Modal::Rename {
                    target: RenameTarget::DescribePattern { bank, pattern },
                    name: current_desc,
                }));
            }
        }
        KeyCode::Char('m') => {
            let bank = ctx.app.patterns_nav.bank_cursor;
            for pattern in ctx.app.patterns_nav.selected_patterns() {
                ctx.dispatch(AppCommand::StageMute { bank, pattern });
            }
        }
        KeyCode::Char('x') => {
            let bank = ctx.app.patterns_nav.bank_cursor;
            for pattern in ctx.app.patterns_nav.selected_patterns() {
                ctx.dispatch(AppCommand::StageSolo { bank, pattern });
            }
        }
        KeyCode::Char('M') => {
            ctx.dispatch(AppCommand::ClearMutes);
            ctx.app.send_mute_state(ctx.seq_cmd_tx);
        }
        KeyCode::Char('X') => {
            ctx.dispatch(AppCommand::ClearSolos);
            ctx.app.send_mute_state(ctx.seq_cmd_tx);
        }
        KeyCode::Char('g') => {
            let bank = ctx.app.patterns_nav.bank_cursor;
            match ctx.app.patterns_nav.column {
                PatternsColumn::Patterns => {
                    let pattern = ctx.app.patterns_nav.pattern_cursor;
                    ctx.dispatch(AppCommand::SharePattern { bank, pattern });
                }
                PatternsColumn::Banks => {
                    ctx.dispatch(AppCommand::ShareBank { bank });
                }
            }
        }
        KeyCode::Char('G') => {
            let bank = ctx.app.patterns_nav.bank_cursor;
            match ctx.app.patterns_nav.column {
                PatternsColumn::Patterns => {
                    let pattern = ctx.app.patterns_nav.pattern_cursor;
                    ctx.dispatch(AppCommand::ImportPattern { bank, pattern });
                }
                PatternsColumn::Banks => {
                    ctx.dispatch(AppCommand::OpenModal(Modal::Confirm {
                        action: ConfirmAction::ImportBank { bank },
                        selected: false,
                    }));
                }
            }
        }
        KeyCode::Char('s') => super::open_save(ctx),
        KeyCode::Char('l') => super::open_load(ctx),
        KeyCode::Char('?') => {
            ctx.dispatch(AppCommand::OpenModal(Modal::KeybindingsHelp { scroll: 0 }));
        }
        _ => {}
    }
    InputResult::Continue
}
