use crate::*;

#[uniffi::export(async_runtime = "tokio")]
impl GotchaCore {
    pub async fn pull_filters(&self) -> Result<PullFilterOptions, GotchaError> {
        let server = self.server()?;
        let filter = self
            .state
            .lock()
            .unwrap()
            .preferences
            .pull_filters
            .get(&server.url)
            .cloned()
            .unwrap_or_default();
        Ok(pull_filter_options(
            &load_pull_milestones(&server).await?,
            &filter,
        ))
    }

    pub fn pull_filters_active(&self) -> Result<bool, GotchaError> {
        let server = self.server()?;
        let state = self.state.lock().unwrap();
        let filter = state
            .preferences
            .pull_filters
            .get(&server.url)
            .cloned()
            .unwrap_or_default();
        Ok(filter.is_active(&state.preferences.pull_status))
    }

    pub fn set_pull_filters(
        &self,
        milestone: String,
        search_text: String,
    ) -> Result<(), GotchaError> {
        let filter = PullFilter {
            milestone,
            search_text: search_text.trim().into(),
        };
        let mut state = self.state.lock().unwrap();
        let server = state
            .active_server
            .and_then(|index| state.preferences.servers.get(index))
            .ok_or("Select a server first.")?;
        let key = server.url.clone();
        if filter == PullFilter::default() {
            state.preferences.pull_filters.remove(&key);
        } else {
            state.preferences.pull_filters.insert(key, filter);
        }
        save_preferences(&state.preferences).map_err(Into::into)
    }

    pub fn clear_pull_filters(&self) -> Result<(), GotchaError> {
        let mut state = self.state.lock().unwrap();
        let server = state
            .active_server
            .and_then(|index| state.preferences.servers.get(index))
            .ok_or("Select a server first.")?;
        let key = server.url.clone();
        state.preferences.pull_status = "open".into();
        state.preferences.pull_filters.remove(&key);
        save_preferences(&state.preferences).map_err(Into::into)
    }

    pub async fn pulls(&self, page: u32) -> Result<PullListPage, GotchaError> {
        let server = self.server()?;
        let (status, filter) = {
            let state = self.state.lock().unwrap();
            (
                state.preferences.pull_status.clone(),
                state
                    .preferences
                    .pull_filters
                    .get(&server.url)
                    .cloned()
                    .unwrap_or_default(),
            )
        };
        let page = load_pulls(
            &server,
            &status,
            &filter.milestone,
            &filter.search_text,
            valid_page(page)?,
        )
        .await?;
        Ok(PullListPage {
            rows: pull_rows(&page.items),
            has_more: page.has_more,
        })
    }

    pub async fn pull(
        &self,
        owner: String,
        repository: String,
        number: i64,
        page: u32,
    ) -> Result<PullPage, GotchaError> {
        Ok(pull_page(
            load_pull(
                &self.server()?,
                &owner,
                &repository,
                number,
                valid_page(page)?,
            )
            .await?,
        ))
    }
}
