use edit_prediction::EditPredictionStore;
use gpui::{
    DismissEvent, Entity, EventEmitter, FocusHandle, Focusable, IntoElement, ParentElement, Render,
};
use ui::{Button, ButtonStyle, Clickable, Headline, HeadlineSize, prelude::*};
use ui_input::InputField;
use workspace::ModalView;

pub struct ExternalProviderApiKeyModal {
    api_key_input: Entity<InputField>,
    focus_handle: FocusHandle,
    on_confirm: Box<dyn Fn(Option<String>, &mut EditPredictionStore, &mut App)>,
}

impl ExternalProviderApiKeyModal {
    pub fn new(
        window: &mut Window,
        cx: &mut Context<Self>,
        on_confirm: impl Fn(Option<String>, &mut EditPredictionStore, &mut App) + 'static,
    ) -> Self {
        let api_key_input = cx.new(|cx| InputField::new(window, cx, "Enter your API key"));

        Self {
            api_key_input,
            focus_handle: cx.focus_handle(),
            on_confirm: Box::new(on_confirm),
        }
    }

    fn cancel(&mut self, _: &menu::Cancel, _window: &mut Window, cx: &mut Context<Self>) {
        cx.emit(DismissEvent);
    }

    fn confirm(&mut self, _: &menu::Confirm, _window: &mut Window, cx: &mut Context<Self>) {
        let api_key = self.api_key_input.read(cx).text(cx);
        let api_key = (!api_key.trim().is_empty()).then_some(api_key);

        if let Some(ep_store) = EditPredictionStore::try_global(cx) {
            ep_store.update(cx, |ep_store, cx| (self.on_confirm)(api_key, ep_store, cx))
        }

        cx.emit(DismissEvent);
    }
}

impl EventEmitter<DismissEvent> for ExternalProviderApiKeyModal {}

impl ModalView for ExternalProviderApiKeyModal {}

impl Focusable for ExternalProviderApiKeyModal {
    fn focus_handle(&self, _cx: &App) -> FocusHandle {
        self.focus_handle.clone()
    }
}

impl Render for ExternalProviderApiKeyModal {
    fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
        v_flex()
            .key_context("ExternalApiKeyModal")
            .on_action(cx.listener(Self::cancel))
            .on_action(cx.listener(Self::confirm))
            .elevation_2(cx)
            .w(px(400.))
            .p_4()
            .gap_3()
            .child(Headline::new("API Token").size(HeadlineSize::Small))
            .child(self.api_key_input.clone())
            .child(
                h_flex()
                    .justify_end()
                    .gap_2()
                    .child(Button::new("cancel", "Cancel").on_click(cx.listener(
                        |_, _, _window, cx| {
                            cx.emit(DismissEvent);
                        },
                    )))
                    .child(
                        Button::new("save", "Save")
                            .style(ButtonStyle::Filled)
                            .on_click(cx.listener(|this, _, window, cx| {
                                this.confirm(&menu::Confirm, window, cx);
                            })),
                    ),
            )
    }
}
