use crate::*;

#[uniffi::export(async_runtime = "tokio")]
impl GotchaCore {
    pub async fn milestones(
        &self,
        owner: String,
        repository: String,
        page: u32,
    ) -> Result<MilestoneListPage, GotchaError> {
        let page =
            load_milestones_page(&self.server()?, &owner, &repository, valid_page(page)?).await?;
        Ok(MilestoneListPage {
            rows: milestone_rows(&page.items),
            has_more: page.has_more,
        })
    }

    pub async fn milestone(
        &self,
        owner: String,
        repository: String,
        id: i64,
        page: u32,
    ) -> Result<MilestonePage, GotchaError> {
        Ok(milestone_page(
            load_milestone(&self.server()?, &owner, &repository, id, valid_page(page)?).await?,
        ))
    }

    pub async fn milestone_editor(
        &self,
        owner: String,
        repository: String,
        id: Option<i64>,
    ) -> Result<MilestoneEditorPage, GotchaError> {
        let (owner, repository) = validate_repository(&owner, &repository)?;
        if id.is_some_and(|id| id <= 0) {
            return Err("Invalid milestone selection.".into());
        }
        let milestone = match id {
            Some(id) => Some(load_milestone_editor(&self.server()?, owner, repository, id).await?),
            None => None,
        };
        Ok(milestone_editor_page(milestone))
    }

    pub async fn save_milestone(
        &self,
        owner: String,
        repository: String,
        id: Option<i64>,
        draft: MilestoneEditorPage,
    ) -> Result<i64, GotchaError> {
        let (owner, repository) = validate_repository(&owner, &repository)?;
        let title = draft.title.trim();
        if title.is_empty() {
            return Err("Enter a milestone title.".into());
        }
        if id.is_some_and(|id| id <= 0) {
            return Err("Invalid milestone selection.".into());
        }
        let milestone = save_milestone(
            &self.server()?,
            owner,
            repository,
            id,
            MilestoneDraft {
                title: title.into(),
                description: draft.description,
                due_date: draft.due_date,
                closed: draft.closed,
            },
        )
        .await?;
        milestone
            .id
            .ok_or_else(|| "The saved milestone has no ID.".into())
    }

    pub async fn set_milestone_closed(
        &self,
        owner: String,
        repository: String,
        id: i64,
        closed: bool,
    ) -> Result<(), GotchaError> {
        let (owner, repository) = validate_repository(&owner, &repository)?;
        if id <= 0 {
            return Err("Invalid milestone selection.".into());
        }
        set_milestone_closed(&self.server()?, owner, repository, id, closed).await?;
        Ok(())
    }

    pub async fn delete_milestone(
        &self,
        owner: String,
        repository: String,
        id: i64,
    ) -> Result<(), GotchaError> {
        let (owner, repository) = validate_repository(&owner, &repository)?;
        if id <= 0 {
            return Err("Invalid milestone selection.".into());
        }
        delete_milestone(&self.server()?, owner, repository, id).await?;
        Ok(())
    }
}
