"""
Configuration manager for loading and managing application settings.
"""
import os
import platform
import yaml
import logging
from pathlib import Path
from typing import Dict, Optional
from dotenv import load_dotenv

logger = logging.getLogger(__name__)


class ConfigManager:
    """Manages application configuration from YAML and environment variables."""
    
    def __init__(self, config_path: Optional[str] = None):
        """
        Initialize configuration manager.
        
        Args:
            config_path: Path to config YAML file (default: config/config.yaml)
        """
        # Load environment variables
        load_dotenv()
        
        # Determine config path
        if config_path is None:
            config_path = "config/config.yaml"
        
        self.config_path = Path(config_path)
        self.config = {}
        
        # Load configuration
        self._load_config()
    
    def _load_config(self) -> None:
        """Load configuration from YAML file or create default."""
        if self.config_path.exists():
            try:
                with open(self.config_path, "r") as f:
                    self.config = yaml.safe_load(f) or {}
                logger.info(f"Loaded configuration from {self.config_path}")
            except Exception as e:
                logger.warning(f"Failed to load config file: {e}, using defaults")
                self.config = {}
        else:
            logger.info("Config file not found, using environment variables and defaults")
            self.config = {}
        
        # Override with environment variables
        self._load_from_env()
        
        # Prompt for missing required values
        self._prompt_missing_values()
    
    def _load_from_env(self) -> None:
        """Load configuration from environment variables."""
        # Bitbucket
        if not self.config.get("bitbucket", {}).get("workspace"):
            self.config.setdefault("bitbucket", {})["workspace"] = os.getenv("BITBUCKET_WORKSPACE", "")
        if not self.config.get("bitbucket", {}).get("app_password"):
            self.config.setdefault("bitbucket", {})["app_password"] = os.getenv("BITBUCKET_APP_PASSWORD", "")
        if not self.config.get("bitbucket", {}).get("api_token"):
            self.config.setdefault("bitbucket", {})["api_token"] = os.getenv("BITBUCKET_API_TOKEN", "")
        if not self.config.get("bitbucket", {}).get("username"):
            self.config.setdefault("bitbucket", {})["username"] = os.getenv("BITBUCKET_USERNAME", "")
        
        # SonarQube
        if not self.config.get("sonarqube", {}).get("url"):
            self.config.setdefault("sonarqube", {})["url"] = os.getenv("SONARQUBE_URL", "https://scan.appmonitor.co.za/")
        if not self.config.get("sonarqube", {}).get("token"):
            self.config.setdefault("sonarqube", {})["token"] = os.getenv("SONARQUBE_TOKEN", "")
        
        # Scanning settings
        scanning = self.config.setdefault("scanning", {})
        scanning.setdefault("repos_dir", os.getenv("REPOS_DIR", "./repos"))
        scanning.setdefault("reports_dir", os.getenv("REPORTS_DIR", "./reports"))
        scanning.setdefault("history_file", os.getenv("HISTORY_FILE", "./scan_history.json"))
        # SONAR_SCANNER_PATH overrides YAML; on non-Windows, never use a Windows path
        if os.getenv("SONAR_SCANNER_PATH"):
            scanning["sonar_scanner_path"] = os.getenv("SONAR_SCANNER_PATH")
        else:
            scanning.setdefault("sonar_scanner_path", "sonar-scanner")
        # On Linux/macOS, if config has a Windows path (e.g. from shared config), use CLI command
        if platform.system() != "Windows":
            path = (scanning.get("sonar_scanner_path") or "").strip()
            if "\\" in path or path.endswith(".bat") or path.endswith(".cmd") or "C:" in path:
                scanning["sonar_scanner_path"] = "sonar-scanner"
                logger.info("Using sonar-scanner (Linux); config had Windows path, ignored.")
        try:
            scanning.setdefault("weekly_scan_days", int(os.getenv("WEEKLY_SCAN_DAYS", "7")))
        except (TypeError, ValueError):
            scanning.setdefault("weekly_scan_days", 7)
    
    def _prompt_missing_values(self) -> None:
        """Prompt user for missing required configuration values."""
        # Bitbucket workspace
        if not self.config.get("bitbucket", {}).get("workspace"):
            workspace = input("Enter Bitbucket workspace name: ").strip()
            if workspace:
                self.config.setdefault("bitbucket", {})["workspace"] = workspace
        
        # Bitbucket username (email for API token, username for app password)
        if not self.config.get("bitbucket", {}).get("username"):
            username = input("Enter Bitbucket username/email: ").strip()
            if username:
                self.config.setdefault("bitbucket", {})["username"] = username
        
        # Bitbucket authentication - prefer API token, fallback to app password
        bitbucket_config = self.config.setdefault("bitbucket", {})
        if not bitbucket_config.get("api_token") and not bitbucket_config.get("app_password"):
            use_token = input("Do you want to use API token? (y/n, default: y): ").strip().lower()
            if use_token != 'n':
                api_token = input("Enter Bitbucket API token: ").strip()
                if api_token:
                    bitbucket_config["api_token"] = api_token
            else:
                app_password = input("Enter Bitbucket app password: ").strip()
                if app_password:
                    bitbucket_config["app_password"] = app_password
        
        # SonarQube token
        if not self.config.get("sonarqube", {}).get("token"):
            token = input("Enter SonarQube token: ").strip()
            if token:
                self.config.setdefault("sonarqube", {})["token"] = token
    
    def save_config(self) -> None:
        """Save current configuration to YAML file."""
        try:
            # Create config directory if it doesn't exist
            self.config_path.parent.mkdir(parents=True, exist_ok=True)
            
            # Don't save sensitive data to YAML
            safe_config = {
                "bitbucket": {
                    "workspace": self.config.get("bitbucket", {}).get("workspace", ""),
                    "username": "",  # Don't save
                    "app_password": ""  # Don't save
                },
                "sonarqube": {
                    "url": self.config.get("sonarqube", {}).get("url", ""),
                    "token": ""  # Don't save
                },
                "scanning": self.config.get("scanning", {})
            }
            
            with open(self.config_path, "w") as f:
                yaml.dump(safe_config, f, default_flow_style=False)
            
            logger.info(f"Configuration saved to {self.config_path}")
        except Exception as e:
            logger.warning(f"Failed to save configuration: {e}")
    
    def get(self, key: str, default=None):
        """
        Get configuration value using dot notation.
        
        Args:
            key: Configuration key (e.g., "bitbucket.workspace")
            default: Default value if key not found
            
        Returns:
            Configuration value
        """
        keys = key.split(".")
        value = self.config
        
        for k in keys:
            if isinstance(value, dict):
                value = value.get(k)
                if value is None:
                    return default
            else:
                return default
        
        return value if value is not None else default
    
    def get_all(self) -> Dict:
        """Get all configuration."""
        return self.config.copy()

