//! Page management system for discovering and managing existing pages

use std::collections::HashMap;
use std::fs;
use std::path::{Path, PathBuf};

use anyhow::{Context, Result};
use serde::Deserialize;

/// Represents a discovered page from the routes system
#[derive(Debug, Clone)]
pub struct DiscoveredPage {
    pub name: String,
    pub route_file: PathBuf,
    pub route_config: RouteConfig,
    pub related_files: Vec<RelatedFile>,
    pub languages: Vec<String>,
}

/// Type of related file
#[derive(Debug, Clone)]
pub enum FileType {
    Component,   // Rust component file
    Translation, // FTL translation file
    Route,       // TOML route config
    Style,       // CSS style file
}

/// Related file associated with a page
#[derive(Debug, Clone)]
pub struct RelatedFile {
    pub path: PathBuf,
    pub file_type: FileType,
    pub language: Option<String>, // For translation files
    pub exists: bool,
}

/// Route configuration structure (simplified)
#[derive(Debug, Clone, Deserialize)]
pub struct RouteConfig {
    pub path: String,
    pub template: Option<String>,
    pub priority: Option<f32>,
    pub title: Option<HashMap<String, String>>,
    pub meta: Option<HashMap<String, String>>,
}

/// Page management system
#[derive(Debug)]
pub struct PageManager {
    project_root: PathBuf,
    content_root: PathBuf,
    discovered_pages: Vec<DiscoveredPage>,
}

impl PageManager {
    /// Create new page manager
    pub fn new(project_root: PathBuf) -> Result<Self> {
        // Use new site structure environment variables
        let site_root = std::env::var("SITE_ROOT_PATH").unwrap_or_else(|_| "site".to_string());
        let content_path = std::env::var("SITE_SERVER_ROOT_CONTENT")
            .unwrap_or_else(|_| format!("{}/content", site_root));
        let content_root = project_root.join(&content_path);

        let mut manager = Self {
            project_root,
            content_root,
            discovered_pages: Vec::new(),
        };

        manager.discover_pages()?;
        Ok(manager)
    }

    /// Discover all existing pages from routes configuration
    pub fn discover_pages(&mut self) -> Result<()> {
        // Routes are now in site/config/routes, not site/content/routes
        let site_root = std::env::var("SITE_ROOT_PATH").unwrap_or_else(|_| "site".to_string());
        let config_path =
            std::env::var("SITE_CONFIG_PATH").unwrap_or_else(|_| format!("{}/config", site_root));
        let routes_dir = self.project_root.join(&config_path).join("routes");

        if !routes_dir.exists() {
            return Ok(()); // No routes directory
        }

        self.discovered_pages.clear();
        self.scan_routes_directory(&routes_dir)?;

        Ok(())
    }

    /// Recursively scan routes directory for TOML files
    fn scan_routes_directory(&mut self, dir: &Path) -> Result<()> {
        let entries = fs::read_dir(dir)
            .with_context(|| format!("Failed to read routes directory: {:?}", dir))?;

        for entry in entries {
            let entry = entry?;
            let path = entry.path();

            if path.is_dir() {
                // Recursively scan subdirectories
                self.scan_routes_directory(&path)?;
            } else if path.extension().is_some_and(|ext| ext == "toml") {
                // Process TOML route file
                if let Ok(page) = self.process_route_file(&path) {
                    self.discovered_pages.push(page);
                }
            }
        }

        Ok(())
    }

    /// Process a single route TOML file
    fn process_route_file(&self, route_file: &Path) -> Result<DiscoveredPage> {
        let content = fs::read_to_string(route_file)
            .with_context(|| format!("Failed to read route file: {:?}", route_file))?;

        let route_config: RouteConfig = toml::from_str(&content)
            .with_context(|| format!("Failed to parse route TOML: {:?}", route_file))?;

        // Extract page name from file path
        let page_name = route_file
            .file_stem()
            .and_then(|name| name.to_str())
            .unwrap_or("unknown")
            .to_string();

        // Discover related files
        let related_files = self.discover_related_files(&page_name, &route_config)?;

        // Extract languages from translation files
        let languages = self.extract_languages_from_files(&related_files);

        Ok(DiscoveredPage {
            name: page_name,
            route_file: route_file.to_path_buf(),
            route_config,
            related_files,
            languages,
        })
    }

    /// Discover files related to a page
    fn discover_related_files(
        &self,
        page_name: &str,
        route_config: &RouteConfig,
    ) -> Result<Vec<RelatedFile>> {
        let mut related_files = Vec::new();

        // Add the route file itself
        let route_file_path = self
            .content_root
            .join("routes")
            .join(format!("{}.toml", page_name));
        related_files.push(RelatedFile {
            path: route_file_path.clone(),
            file_type: FileType::Route,
            language: None,
            exists: route_file_path.exists(),
        });

        // Look for component files in crates/pages/src/
        let component_path = self
            .project_root
            .join("crates")
            .join("pages")
            .join("src")
            .join(format!("{}.rs", page_name));

        related_files.push(RelatedFile {
            path: component_path.clone(),
            file_type: FileType::Component,
            language: None,
            exists: component_path.exists(),
        });

        // Look for translation files based on route title
        if let Some(titles) = &route_config.title {
            for lang in titles.keys() {
                let ftl_path = self
                    .content_root
                    .join("locales")
                    .join(format!("{}.ftl", lang));

                related_files.push(RelatedFile {
                    path: ftl_path.clone(),
                    file_type: FileType::Translation,
                    language: Some(lang.clone()),
                    exists: ftl_path.exists(),
                });
            }
        }

        // Look for common translation files (en, es)
        for lang in ["en", "es"] {
            let ftl_path = self
                .content_root
                .join("locales")
                .join(format!("{}.ftl", lang));

            // Only add if not already added and exists
            if ftl_path.exists() && !related_files.iter().any(|f| f.path == ftl_path) {
                related_files.push(RelatedFile {
                    path: ftl_path,
                    file_type: FileType::Translation,
                    language: Some(lang.to_string()),
                    exists: true,
                });
            }
        }

        Ok(related_files)
    }

    /// Extract languages from related translation files
    fn extract_languages_from_files(&self, files: &[RelatedFile]) -> Vec<String> {
        files
            .iter()
            .filter(|f| matches!(f.file_type, FileType::Translation) && f.exists)
            .filter_map(|f| f.language.clone())
            .collect()
    }

    /// Get all discovered pages
    pub fn get_pages(&self) -> &[DiscoveredPage] {
        &self.discovered_pages
    }

    /// Find page by name
    pub fn find_page(&self, name: &str) -> Option<&DiscoveredPage> {
        self.discovered_pages.iter().find(|p| p.name == name)
    }

    /// Get files for multi-tab editing
    pub fn get_editable_files(&self, page_name: &str, include_non_existing: bool) -> Vec<PathBuf> {
        if let Some(page) = self.find_page(page_name) {
            page.related_files
                .iter()
                .filter(|f| include_non_existing || f.exists)
                .map(|f| f.path.clone())
                .collect()
        } else {
            Vec::new()
        }
    }

    /// Refresh page discovery
    pub fn refresh(&mut self) -> Result<()> {
        self.discover_pages()
    }
}
