//! App-level handlers for ambient terminal pet events.

use super::*;

impl App {
    pub(super) fn disable_ambient_pet_before_shutdown(&mut self, tui: &mut tui::Tui) -> Result<()> {
        self.chat_widget.disable_ambient_pet_for_session();
        if let Err(clear_err) = tui.clear_ambient_pet_image() {
            match clear_err {
                crate::pets::PetImageRenderError::Terminal(err) => return Err(err.into()),
                crate::pets::PetImageRenderError::Asset(err) => {
                    tracing::warn!(
                        error = %err,
                        "failed to clear ambient pet image before shutdown feedback"
                    );
                }
            }
        }
        Ok(())
    }

    pub(super) fn handle_ambient_pet_image_render_error(
        &mut self,
        tui: &mut tui::Tui,
        err: crate::pets::PetImageRenderError,
    ) -> Result<()> {
        match err {
            crate::pets::PetImageRenderError::Terminal(err) => Err(err.into()),
            crate::pets::PetImageRenderError::Asset(err) => {
                tracing::warn!(
                    error = %err,
                    "failed to render ambient pet image; disabling pet for session"
                );
                self.chat_widget.disable_ambient_pet_for_session();
                if let Err(clear_err) = tui.clear_ambient_pet_image() {
                    match clear_err {
                        crate::pets::PetImageRenderError::Terminal(err) => return Err(err.into()),
                        crate::pets::PetImageRenderError::Asset(err) => {
                            tracing::warn!(
                                error = %err,
                                "failed to clear ambient pet image after render failure"
                            );
                        }
                    }
                }
                Ok(())
            }
        }
    }

    pub(super) fn handle_pet_picker_preview_image_render_error(
        &mut self,
        tui: &mut tui::Tui,
        err: crate::pets::PetImageRenderError,
    ) -> Result<()> {
        match err {
            crate::pets::PetImageRenderError::Terminal(err) => Err(err.into()),
            crate::pets::PetImageRenderError::Asset(err) => {
                tracing::warn!(error = %err, "failed to render pet picker preview image");
                self.chat_widget
                    .fail_pet_picker_preview_render(err.to_string());
                if let Err(clear_err) = tui.draw_pet_picker_preview_image(/*request*/ None) {
                    match clear_err {
                        crate::pets::PetImageRenderError::Terminal(err) => return Err(err.into()),
                        crate::pets::PetImageRenderError::Asset(err) => {
                            tracing::warn!(
                                error = %err,
                                "failed to clear pet picker preview image after render failure"
                            );
                        }
                    }
                }
                Ok(())
            }
        }
    }

    pub(super) fn handle_pet_selected(&mut self, tui: &mut tui::Tui, pet_id: String) {
        let request_id = self.chat_widget.show_pet_selection_loading_popup();
        tui.frame_requester().schedule_frame();
        let codex_home = self.config.codex_home.clone();
        let frame_requester = tui.frame_requester();
        let animations_enabled = self.config.animations;
        let tx = self.app_event_tx.clone();
        std::mem::drop(tokio::task::spawn_blocking(move || {
            let result = crate::pets::ensure_builtin_pack_for_pet(&pet_id, &codex_home)
                .and_then(|()| {
                    crate::pets::AmbientPet::load(
                        Some(&pet_id),
                        &codex_home,
                        frame_requester,
                        animations_enabled,
                    )
                })
                .map(Some)
                .map_err(|err| err.to_string());
            tx.send(AppEvent::PetSelectionLoaded {
                request_id,
                pet_id,
                result,
            });
        }));
    }

    pub(super) async fn handle_pet_disabled(&mut self, tui: &mut tui::Tui) {
        let edit = crate::legacy_core::config::edit::tui_pet_edit(crate::pets::DISABLED_PET_ID);
        let apply_result = ConfigEditsBuilder::new(&self.config.codex_home)
            .with_edits([edit])
            .apply()
            .await;
        match apply_result {
            Ok(()) => {
                self.sync_tui_pet_disabled();
                tui.frame_requester().schedule_frame();
            }
            Err(err) => {
                self.chat_widget
                    .add_error_message(format!("Failed to disable pets: {err}"));
            }
        }
    }

    pub(super) fn handle_pet_preview_loaded(
        &mut self,
        tui: &mut tui::Tui,
        request_id: u64,
        result: Result<crate::pets::AmbientPet, String>,
    ) {
        self.chat_widget
            .finish_pet_picker_preview_load(request_id, result);
        tui.frame_requester().schedule_frame();
    }

    pub(super) async fn handle_pet_selection_loaded(
        &mut self,
        tui: &mut tui::Tui,
        request_id: u64,
        pet_id: String,
        result: Result<Option<crate::pets::AmbientPet>, String>,
    ) -> Result<AppRunControl> {
        if !self
            .chat_widget
            .finish_pet_selection_loading_popup(request_id)
        {
            return Ok(AppRunControl::Continue);
        }
        match result {
            Ok(ambient_pet) => {
                let edit = crate::legacy_core::config::edit::tui_pet_edit(&pet_id);
                match ConfigEditsBuilder::new(&self.config.codex_home)
                    .with_edits([edit])
                    .apply()
                    .await
                {
                    Ok(()) => {
                        self.config.tui_pet = Some(pet_id.clone());
                        self.chat_widget
                            .set_tui_pet_loaded(Some(pet_id), ambient_pet);
                    }
                    Err(err) => {
                        self.chat_widget
                            .add_error_message(format!("Failed to save pet selection: {err}"));
                    }
                }
            }
            Err(err) => {
                self.chat_widget
                    .add_error_message(format!("Failed to load pet: {err}"));
            }
        }
        tui.frame_requester().schedule_frame();
        Ok(AppRunControl::Continue)
    }

    pub(super) fn handle_configured_pet_loaded(
        &mut self,
        tui: &mut tui::Tui,
        pet_id: String,
        result: Result<Option<crate::pets::AmbientPet>, String>,
    ) {
        if self.config.tui_pet.as_deref() != Some(pet_id.as_str()) {
            return;
        }

        match result {
            Ok(ambient_pet) => {
                self.chat_widget
                    .set_tui_pet_loaded(Some(pet_id), ambient_pet);
                tui.frame_requester().schedule_frame();
            }
            Err(err) => {
                self.chat_widget
                    .add_warning_message(format!("Failed to load configured pet: {err}"));
            }
        }
    }
}
