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

use super::{InputContext, InputResult};
use crate::commands::AppCommand;
use crate::state::{
    ConfirmAction, CyclicEnum, EuclideanField, Modal, PanelFocus, PatternField, RenameTarget,
    SampleBrowserState, SidePanel,
};

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

    match key.code {
        KeyCode::Tab => {
            if ctx.app.panel.visible {
                ctx.app.panel.visible = false;
                ctx.app.panel.focus = PanelFocus::Main;
            } else {
                let state = SampleBrowserState::new(&ctx.app.audio.config.sample_paths);
                ctx.app.panel.side = Some(SidePanel::SampleBrowser(state));
                ctx.app.panel.visible = true;
                ctx.app.panel.focus = PanelFocus::Side;
            }
        }
        KeyCode::Char('q') if !ctx.app.plugin_mode => {
            ctx.dispatch(AppCommand::OpenModal(Modal::Confirm {
                action: ConfirmAction::Quit,
                selected: false,
            }));
        }
        KeyCode::Char(' ') if !ctx.app.plugin_mode => {
            ctx.dispatch(AppCommand::TogglePlaying);
            ctx.playing
                .store(ctx.app.playback.playing, Ordering::Relaxed);
        }
        KeyCode::Left if shift && !ctrl => {
            if ctx.app.editor_ctx.selection_anchor.is_none() {
                ctx.dispatch(AppCommand::SetSelectionAnchor(ctx.app.editor_ctx.step));
            }
            ctx.dispatch(AppCommand::PrevStep);
        }
        KeyCode::Right if shift && !ctrl => {
            if ctx.app.editor_ctx.selection_anchor.is_none() {
                ctx.dispatch(AppCommand::SetSelectionAnchor(ctx.app.editor_ctx.step));
            }
            ctx.dispatch(AppCommand::NextStep);
        }
        KeyCode::Up if shift && !ctrl => {
            if ctx.app.editor_ctx.selection_anchor.is_none() {
                ctx.dispatch(AppCommand::SetSelectionAnchor(ctx.app.editor_ctx.step));
            }
            ctx.dispatch(AppCommand::StepUp);
        }
        KeyCode::Down if shift && !ctrl => {
            if ctx.app.editor_ctx.selection_anchor.is_none() {
                ctx.dispatch(AppCommand::SetSelectionAnchor(ctx.app.editor_ctx.step));
            }
            ctx.dispatch(AppCommand::StepDown);
        }
        KeyCode::Left => {
            ctx.app.editor_ctx.clear_selection();
            ctx.dispatch(AppCommand::PrevStep);
        }
        KeyCode::Right => {
            ctx.app.editor_ctx.clear_selection();
            ctx.dispatch(AppCommand::NextStep);
        }
        KeyCode::Up => {
            ctx.app.editor_ctx.clear_selection();
            ctx.dispatch(AppCommand::StepUp);
        }
        KeyCode::Down => {
            ctx.app.editor_ctx.clear_selection();
            ctx.dispatch(AppCommand::StepDown);
        }
        KeyCode::Esc => {
            ctx.app.editor_ctx.clear_selection();
        }
        KeyCode::Enter => {
            ctx.app.editor_ctx.clear_selection();
            ctx.dispatch(AppCommand::OpenModal(Modal::Editor));
        }
        KeyCode::Char('t') => ctx.dispatch(AppCommand::ToggleSteps),
        KeyCode::Char('s') => super::open_save(ctx),
        KeyCode::Char('z') if ctrl && !shift => {
            ctx.dispatch(AppCommand::Undo);
        }
        KeyCode::Char('Z') if ctrl => {
            ctx.dispatch(AppCommand::Redo);
        }
        KeyCode::Char('c') if ctrl => {
            ctx.dispatch(AppCommand::CopySteps);
        }
        KeyCode::Char('v') if ctrl => {
            ctx.dispatch(AppCommand::PasteSteps);
        }
        KeyCode::Char('b') if ctrl => {
            ctx.dispatch(AppCommand::LinkPasteSteps);
        }
        KeyCode::Char('d') if ctrl => {
            ctx.dispatch(AppCommand::DuplicateSteps);
        }
        KeyCode::Char('h') if ctrl => ctx.dispatch(AppCommand::HardenSteps),
        KeyCode::Char('l') => super::open_load(ctx),
        KeyCode::Char('+') | KeyCode::Char('=') if !ctx.app.plugin_mode => {
            ctx.dispatch(AppCommand::TempoUp);
        }
        KeyCode::Char('-') if !ctx.app.plugin_mode => ctx.dispatch(AppCommand::TempoDown),
        KeyCode::Char('T') if !ctx.app.plugin_mode => {
            let current = format!("{:.1}", ctx.link.tempo());
            ctx.dispatch(AppCommand::OpenModal(Modal::SetTempo(current)));
        }
        KeyCode::Char(':') => {
            ctx.dispatch(AppCommand::OpenModal(Modal::JumpToStep(String::new())));
        }
        KeyCode::Char('<') | KeyCode::Char(',') => ctx.dispatch(AppCommand::LengthDecrease),
        KeyCode::Char('>') | KeyCode::Char('.') => ctx.dispatch(AppCommand::LengthIncrease),
        KeyCode::Char('[') => ctx.dispatch(AppCommand::SpeedDecrease),
        KeyCode::Char(']') => ctx.dispatch(AppCommand::SpeedIncrease),
        KeyCode::Char('L') => ctx.dispatch(AppCommand::OpenPatternModal(PatternField::Length)),
        KeyCode::Char('S') => ctx.dispatch(AppCommand::OpenPatternModal(PatternField::Speed)),
        KeyCode::Char('p') => ctx.dispatch(AppCommand::OpenPreludeEditor),
        KeyCode::Delete | KeyCode::Backspace => {
            let (bank, pattern) = (ctx.app.editor_ctx.bank, ctx.app.editor_ctx.pattern);
            if let Some(range) = ctx.app.editor_ctx.selection_range() {
                let steps: Vec<usize> = range.collect();
                ctx.dispatch(AppCommand::OpenModal(Modal::Confirm {
                    action: ConfirmAction::DeleteSteps {
                        bank,
                        pattern,
                        steps,
                    },
                    selected: false,
                }));
            } else {
                let step = ctx.app.editor_ctx.step;
                ctx.dispatch(AppCommand::OpenModal(Modal::Confirm {
                    action: ConfirmAction::DeleteStep {
                        bank,
                        pattern,
                        step,
                    },
                    selected: false,
                }));
            }
        }
        KeyCode::Char('r') if ctrl => {
            let pattern = ctx.app.current_edit_pattern();
            if let Some(script) = pattern.resolve_script(ctx.app.editor_ctx.step) {
                if !script.trim().is_empty() {
                    match ctx
                        .app
                        .execute_script_oneshot(script, ctx.link, ctx.audio_tx)
                    {
                        Ok(()) => ctx
                            .app
                            .ui
                            .flash("Executed", 100, crate::state::FlashKind::Info),
                        Err(e) => ctx.app.ui.flash(
                            &format!("Error: {e}"),
                            200,
                            crate::state::FlashKind::Error,
                        ),
                    }
                }
            }
        }
        KeyCode::Char('r') => {
            let (bank, pattern, step) = (
                ctx.app.editor_ctx.bank,
                ctx.app.editor_ctx.pattern,
                ctx.app.editor_ctx.step,
            );
            let current_name = ctx
                .app
                .current_edit_pattern()
                .step(step)
                .and_then(|s| s.name.clone())
                .unwrap_or_default();
            ctx.dispatch(AppCommand::OpenModal(Modal::Rename {
                target: RenameTarget::Step {
                    bank,
                    pattern,
                    step,
                },
                name: current_name,
            }));
        }
        KeyCode::Char('o') => {
            ctx.app.audio.config.layout = ctx.app.audio.config.layout.next();
        }
        KeyCode::Char('?') => {
            ctx.dispatch(AppCommand::OpenModal(Modal::KeybindingsHelp { scroll: 0 }));
        }
        KeyCode::Char('e') | KeyCode::Char('E') => {
            let (bank, pattern, step) = (
                ctx.app.editor_ctx.bank,
                ctx.app.editor_ctx.pattern,
                ctx.app.editor_ctx.step,
            );
            let pattern_len = ctx.app.current_edit_pattern().length;
            let default_steps = pattern_len.min(32);
            let default_pulses = (default_steps / 2).max(1).min(default_steps);
            ctx.dispatch(AppCommand::OpenModal(Modal::EuclideanDistribution {
                bank,
                pattern,
                source_step: step,
                field: EuclideanField::Pulses,
                pulses: default_pulses.to_string(),
                steps: default_steps.to_string(),
                rotation: "0".to_string(),
            }));
        }
        KeyCode::Char('m') => {
            let (bank, pattern) = (ctx.app.editor_ctx.bank, ctx.app.editor_ctx.pattern);
            ctx.app.mute.toggle_mute(bank, pattern);
            ctx.app.send_mute_state(ctx.seq_cmd_tx);
        }
        KeyCode::Char('x') => {
            let (bank, pattern) = (ctx.app.editor_ctx.bank, ctx.app.editor_ctx.pattern);
            ctx.app.mute.toggle_solo(bank, pattern);
            ctx.app.send_mute_state(ctx.seq_cmd_tx);
        }
        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('d') => {
            ctx.dispatch(AppCommand::EvaluatePrelude);
        }
        KeyCode::Char('g') => {
            let (bank, pattern) = (ctx.app.editor_ctx.bank, ctx.app.editor_ctx.pattern);
            ctx.dispatch(AppCommand::SharePattern { bank, pattern });
        }
        KeyCode::Char('G') => {
            let (bank, pattern) = (ctx.app.editor_ctx.bank, ctx.app.editor_ctx.pattern);
            ctx.dispatch(AppCommand::ImportPattern { bank, pattern });
        }
        _ => {}
    }
    InputResult::Continue
}
