//! Apple App Store Connect API publisher.
//!
//! Models the App Store Connect API calls. Stub the actual HTTP — structure is
//! correct and complete. A future agent fills in the `reqwest` calls.
//!
//! API reference: https://developer.apple.com/documentation/appstoreconnectapi

use crate::{
    config::{AppleConfig, PublishConfig},
    metadata::StoreMetadata,
    PublishError, PublishOutcome, PublishResult,
};

/// Publishes app builds to Apple App Store Connect / TestFlight.
pub struct ApplePublisher {
    pub apple_config: AppleConfig,
    pub publish_config: PublishConfig,
    /// API key for App Store Connect (loaded from env or keychain).
    #[allow(dead_code)]
    api_key: Option<String>,
}

impl ApplePublisher {
    pub fn new(publish_config: PublishConfig) -> PublishResult<Self> {
        let apple_config = publish_config.apple.clone().ok_or_else(|| {
            PublishError::Config("no [publish.apple] section in el.toml".into())
        })?;
        Ok(Self {
            apple_config,
            publish_config,
            api_key: std::env::var("APP_STORE_CONNECT_API_KEY").ok(),
        })
    }

    /// Upload a build to TestFlight.
    ///
    /// In production, this calls the App Store Connect API:
    ///   POST /v1/builds
    ///   PUT  /v1/builds/{id}/betaAppReviewDetail
    ///   POST /v1/betaTestersConfigurations
    pub fn upload_to_testflight(
        &self,
        ipa_path: &str,
    ) -> PublishResult<String> {
        // TODO: use reqwest to call App Store Connect API:
        //   1. Authenticate with JWT from API key
        //   2. POST /v1/builds with IPA binary
        //   3. Poll build status until "READY_FOR_BETA_SUBMISSION"
        //   4. Submit to TestFlight review
        let _ = ipa_path;
        let submission_id = format!(
            "TF-{}-{}",
            self.apple_config.bundle_id,
            self.publish_config.build_number
        );
        Ok(submission_id)
    }

    /// Submit to App Store review.
    ///
    /// In production:
    ///   POST /v1/appStoreVersionSubmissions
    ///   POST /v1/appStoreVersions/{id}/appStoreVersionLocalizations (for metadata)
    pub fn submit_to_app_store(
        &self,
        build_id: &str,
        metadata: &StoreMetadata,
    ) -> PublishResult<String> {
        // TODO: actual API calls
        let _ = (build_id, metadata);
        let review_id = format!("AS-{}", self.publish_config.build_number);
        Ok(review_id)
    }

    /// Set staged rollout percentage on App Store.
    /// Only available after the initial release.
    pub fn set_phased_release(&self, percent: u8) -> PublishResult<()> {
        if percent > 100 {
            return Err(PublishError::Config(format!(
                "rollout percent {} exceeds 100",
                percent
            )));
        }
        // TODO: PATCH /v1/appStoreVersionPhasedReleases/{id}
        let _ = percent;
        Ok(())
    }

    /// Full publish flow: build → upload → submit.
    pub fn publish(&self, ipa_path: &str, to_beta: bool) -> PublishResult<PublishOutcome> {
        let metadata = StoreMetadata::load_from_dir(&self.publish_config.metadata_dir)?;
        let build_id = self.upload_to_testflight(ipa_path)?;

        let track = if to_beta { "testflight" } else { "app_store" };

        if !to_beta {
            let review_id = self.submit_to_app_store(&build_id, &metadata)?;
            let _ = review_id;
        }

        if let Some(rollout) = &self.publish_config.rollout {
            self.set_phased_release(rollout.initial_percent)?;
        }

        Ok(PublishOutcome::new("apple", &self.publish_config, track)
            .with_submission_id(build_id))
    }

    /// List existing builds from App Store Connect.
    pub fn list_builds(&self) -> PublishResult<Vec<BuildInfo>> {
        // TODO: GET /v1/builds?filter[bundleId]=...
        Ok(vec![BuildInfo {
            id: format!("build-{}", self.publish_config.build_number),
            version: self.publish_config.version.clone(),
            status: "READY_FOR_DISTRIBUTION".into(),
        }])
    }
}

/// Info about a build in App Store Connect.
#[derive(Debug, Clone)]
pub struct BuildInfo {
    pub id: String,
    pub version: String,
    pub status: String,
}
