use crossterm::event::{KeyCode, KeyEvent, KeyEventKind};
use color_eyre::Result;
use ratatui::{
    layout::{Position, Alignment, Constraint, Flex, Layout, Rect}, 
    widgets::{Block, Clear, Paragraph}, 
    Frame
};
use tokio::sync::mpsc::UnboundedSender;

use super::{Component, PartialComponent, CurrentTab};
use crate::{
    widgets::{Input, InputRequest},
    action::Action, 
    config::Config, 
    palette::StylePalette, 
};

#[derive(Debug)]
pub struct RenameAccount {
    is_active: bool,
    action_tx: Option<UnboundedSender<Action>>,
    old_name: String,
    name: Input,
    palette: StylePalette
}

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

impl RenameAccount {
    pub fn new() -> Self {
        Self {
            is_active: false,
            old_name: String::new(),
            action_tx: None,
            name: Input::new(String::new()),
            palette: StylePalette::default(),
        }
    }
}

impl RenameAccount {
    fn submit_message(&mut self) {
        if let Some(action_tx) = &self.action_tx {
            let _ = action_tx.send(Action::UpdateAccountName(self.name.value().to_string()));
        }
    }

    fn enter_char(&mut self, new_char: char) {
        let _ = self.name.handle(InputRequest::InsertChar(new_char));
    }

    fn delete_char(&mut self) {
        let _ = self.name.handle(InputRequest::DeletePrevChar);
    }

    fn move_cursor_right(&mut self) {
        let _ = self.name.handle(InputRequest::GoToNextChar);
    }

    fn move_cursor_left(&mut self) {
        let _ = self.name.handle(InputRequest::GoToPrevChar);
    }
}

impl PartialComponent for RenameAccount {
    fn set_active(&mut self, current_tab: CurrentTab) {
        match current_tab {
            CurrentTab::RenameAccount => self.is_active = true,
            _ => {
                self.is_active = false;
                self.old_name = String::new();
                self.name = Input::new(String::new());
            }
        };
    }
}

impl Component for RenameAccount {
    fn register_action_handler(&mut self, tx: UnboundedSender<Action>) -> Result<()> {
        self.action_tx = Some(tx);
        Ok(())
    }

    fn register_config_handler(&mut self, config: Config) -> Result<()> {
        if let Some(style) = config.styles.get(&crate::app::Mode::Wallet) {
            self.palette.with_normal_style(style.get("normal_style").copied());
            self.palette.with_normal_border_style(style.get("normal_border_style").copied());
            self.palette.with_normal_title_style(style.get("normal_title_style").copied());
            self.palette.with_popup_style(style.get("popup_style").copied());
            self.palette.with_popup_title_style(style.get("popup_title_style").copied());
        }
        Ok(())
    }

    fn update(&mut self, action: Action) -> Result<Option<Action>> {
        match action {
            Action::RenameAccount(old_name) => self.old_name = old_name,
            _ => {}
        };
        Ok(None)
    }

    fn handle_key_event(&mut self, key: KeyEvent) -> Result<Option<Action>> {
        if self.is_active && key.kind == KeyEventKind::Press {
            match key.code {
                KeyCode::Enter => self.submit_message(),
                KeyCode::Char(to_insert) => self.enter_char(to_insert),
                KeyCode::Backspace => self.delete_char(),
                KeyCode::Left => self.move_cursor_left(),
                KeyCode::Right => self.move_cursor_right(),
                KeyCode::Esc => self.is_active = false, 
                _ => {},
            };
        }
        Ok(None)
    }

    fn draw(&mut self, frame: &mut Frame, area: Rect) -> Result<()> {
        if self.is_active {
            let (border_style, border_type) = self.palette.create_popup_style();
            let input = Paragraph::new(self.name.value())
                .block(Block::bordered()
                    .border_style(border_style)
                    .border_type(border_type)
                    .title_style(self.palette.create_popup_title_style())
                    .title_alignment(Alignment::Right)
                    .title(format!("New name for '{}'", self.old_name)));
            let v = Layout::vertical([Constraint::Max(3)]).flex(Flex::Center);
            let h = Layout::horizontal([Constraint::Max(50)]).flex(Flex::Center);
            let [area] = v.areas(area);
            let [area] = h.areas(area);

            frame.render_widget(Clear, area);
            frame.render_widget(input, area);
            frame.set_cursor_position(Position::new(
                    area.x + self.name.cursor() as u16 + 1,
                    area.y + 1
            ));
        }
        Ok(())
    }
}