//! el-publish — App Store and Play Store publishing pipeline for el-ui.
//!
//! One command ships to every platform:
//! ```bash
//! el publish              # all platforms
//! el publish --apple      # App Store only
//! el publish --google     # Play Store only
//! el publish --beta       # TestFlight + Play internal track
//! ```
//!
//! Configuration in `el.toml`:
//! ```toml
//! [publish]
//! version = "1.0.0"
//! build_number = 42
//!
//! [publish.apple]
//! account = "will@neurontechnologies.ai"
//! bundle_id = "ai.neurontechnologies.myapp"
//!
//! [publish.google]
//! package = "ai.neurontechnologies.myapp"
//! track = "internal"
//! ```

pub mod apple;
pub mod cert;
pub mod config;
pub mod google;
pub mod metadata;
pub mod rollout;
pub mod screenshot;

pub use apple::ApplePublisher;
pub use cert::{CertInfo, CertStore};
pub use config::{AppleConfig, GoogleConfig, PublishConfig, RolloutConfig};
pub use google::GooglePublisher;
pub use metadata::StoreMetadata;
pub use rollout::RolloutMonitor;
pub use screenshot::{ScreenshotCapture, ScreenshotTarget};

#[cfg(test)]
mod tests;

use thiserror::Error;

#[derive(Debug, Error)]
pub enum PublishError {
    #[error("config error: {0}")]
    Config(String),
    #[error("build error: {0}")]
    Build(String),
    #[error("upload error: {0}")]
    Upload(String),
    #[error("certificate error: {0}")]
    Certificate(String),
    #[error("metadata error: {0}")]
    Metadata(String),
    #[error("api error: {status} {body}")]
    Api { status: u16, body: String },
    #[error("io error: {0}")]
    Io(String),
}

pub type PublishResult<T> = Result<T, PublishError>;

/// The outcome of a publish operation.
#[derive(Debug, Clone)]
pub struct PublishOutcome {
    pub platform: String,
    pub version: String,
    pub build_number: u32,
    pub track: String,
    pub rollout_percent: u8,
    pub submission_id: Option<String>,
}

impl PublishOutcome {
    pub fn new(
        platform: impl Into<String>,
        config: &PublishConfig,
        track: impl Into<String>,
    ) -> Self {
        Self {
            platform: platform.into(),
            version: config.version.clone(),
            build_number: config.build_number,
            track: track.into(),
            rollout_percent: config.rollout.as_ref().map(|r| r.initial_percent).unwrap_or(100),
            submission_id: None,
        }
    }

    pub fn with_submission_id(mut self, id: impl Into<String>) -> Self {
        self.submission_id = Some(id.into());
        self
    }
}
