//! Store metadata — reads title.txt, description.txt, whats-new.txt, etc.
//!
//! Directory structure (mirrors Fastlane's metadata format):
//! ```text
//! store/
//!   en-US/
//!     title.txt
//!     description.txt
//!     whats-new.txt
//!     keywords.txt
//!     promotional-text.txt
//!   de-DE/
//!     title.txt
//!     ...
//! ```

use crate::{PublishError, PublishResult};
use std::collections::HashMap;
use std::path::Path;

/// Metadata for a single locale.
#[derive(Debug, Clone, Default)]
pub struct LocaleMetadata {
    pub title: String,
    pub description: String,
    pub whats_new: String,
    pub keywords: Vec<String>,
    pub promotional_text: String,
}

impl LocaleMetadata {
    pub fn new(title: impl Into<String>, description: impl Into<String>) -> Self {
        Self {
            title: title.into(),
            description: description.into(),
            ..Default::default()
        }
    }

    pub fn with_whats_new(mut self, whats_new: impl Into<String>) -> Self {
        self.whats_new = whats_new.into();
        self
    }
}

/// Complete store metadata across all locales.
#[derive(Debug, Clone, Default)]
pub struct StoreMetadata {
    pub locales: HashMap<String, LocaleMetadata>,
}

impl StoreMetadata {
    pub fn new() -> Self {
        Self::default()
    }

    pub fn add_locale(mut self, locale: impl Into<String>, metadata: LocaleMetadata) -> Self {
        self.locales.insert(locale.into(), metadata);
        self
    }

    /// Get metadata for a specific locale, falling back to `en-US`.
    pub fn for_locale(&self, locale: &str) -> Option<&LocaleMetadata> {
        self.locales.get(locale).or_else(|| self.locales.get("en-US"))
    }

    /// Load metadata from the directory structure.
    ///
    /// Falls back gracefully: if the metadata directory doesn't exist,
    /// returns empty metadata (don't fail the publish for missing store copy).
    pub fn load_from_dir(dir: &str) -> PublishResult<Self> {
        let path = Path::new(dir);
        if !path.exists() {
            // Warn but don't fail — metadata is optional for internal/alpha builds.
            return Ok(Self::new());
        }

        let mut metadata = Self::new();

        let read_dir = std::fs::read_dir(path).map_err(|e| {
            PublishError::Metadata(format!("failed to read metadata dir {}: {}", dir, e))
        })?;

        for entry in read_dir.flatten() {
            let locale_path = entry.path();
            if !locale_path.is_dir() {
                continue;
            }
            let locale = locale_path
                .file_name()
                .and_then(|n| n.to_str())
                .unwrap_or("")
                .to_string();
            if locale.is_empty() {
                continue;
            }

            let locale_meta = LocaleMetadata {
                title: read_file(&locale_path, "title.txt"),
                description: read_file(&locale_path, "description.txt"),
                whats_new: read_file(&locale_path, "whats-new.txt"),
                keywords: read_file(&locale_path, "keywords.txt")
                    .split(',')
                    .map(|k| k.trim().to_string())
                    .filter(|k| !k.is_empty())
                    .collect(),
                promotional_text: read_file(&locale_path, "promotional-text.txt"),
            };

            metadata.locales.insert(locale, locale_meta);
        }

        Ok(metadata)
    }
}

fn read_file(dir: &Path, filename: &str) -> String {
    std::fs::read_to_string(dir.join(filename))
        .unwrap_or_default()
        .trim()
        .to_string()
}
