#!/usr/bin/env python3
"""
Configuration Management

Loads configuration from YAML file or environment variables.
"""

import os
import yaml
import logging
from pathlib import Path
from typing import Dict, Optional, Any

try:
    from dotenv import load_dotenv
    DOTENV_AVAILABLE = True
except ImportError:
    DOTENV_AVAILABLE = False

DEFAULT_CONFIG = {
    'sharepoint': {
        'enabled': False,
        'site_url': '',
        'folder_path': '/Shared Documents/Reports',
        'file_path': None,  # Use folder_path for multiple files, file_path for single file
        'local_dir': 'reports',
        'username': None,
        'password': None,
        'client_id': None,
        'client_secret': None,
        'use_app_authentication': False,
        'file_pattern': '*.xlsx',
        'overwrite': True
    },
    'scheduler': {
        'enabled': False,
        'schedule_type': 'cron',  # 'interval', 'cron', or 'once'
        'interval_hours': 24,  # For interval type
        'cron_expression': '0 10 * * *',  # For cron type (10 AM EST/EDT daily)
        'timezone': 'America/New_York'  # EST/EDT timezone
    },
    'api': {
        'enabled': False,
        'host': '0.0.0.0',
        'port': 8080,
        'api_key': None  # Optional API key for authentication
    },
    'report': {
        'output_dir': 'output',
        'reports_dir': 'reports'
    }
}


def load_config(config_path: Optional[str] = None) -> Dict[str, Any]:
    """
    Load configuration from YAML file or environment variables.
    
    Args:
        config_path: Path to config.yaml file (default: config.yaml in current directory)
    
    Returns:
        Configuration dictionary
    """
    # Load .env file if available (from current directory or parent taskboard directory)
    if DOTENV_AVAILABLE:
        # Try loading from vendor_report/.env first
        env_file = Path(__file__).parent / ".env"
        if not env_file.exists():
            # Try loading from parent taskboard/.env
            parent_env = Path(__file__).parent.parent / "taskboard" / ".env"
            if parent_env.exists():
                env_file = parent_env
                logging.info(f"Found .env file in taskboard directory: {env_file}")
            else:
                logging.warning(f".env file not found in vendor_report or taskboard directory")
                logging.warning(f"Checked: {Path(__file__).parent / '.env'}")
                logging.warning(f"Checked: {parent_env}")
        else:
            logging.info(f"Found .env file in vendor_report directory: {env_file}")
        
        if env_file.exists():
            load_dotenv(env_file, override=True)  # override=True ensures env vars take precedence
            logging.info(f"Loaded environment variables from {env_file.absolute()}")
            
            # Log which SharePoint env vars were found (checking both SHAREPOINT_* and AZURE_AD_* fallbacks)
            sp_vars = ['SHAREPOINT_ENABLED', 'SHAREPOINT_SITE_URL', 'SHAREPOINT_FOLDER_PATH']
            found_vars = [var for var in sp_vars if os.getenv(var)]
            
            # Check credentials (with fallback)
            client_id = os.getenv('SHAREPOINT_CLIENT_ID') or os.getenv('AZURE_AD_CLIENT_ID')
            tenant_id = os.getenv('SHAREPOINT_TENANT_ID') or os.getenv('AZURE_AD_TENANT_ID')
            client_secret = os.getenv('SHAREPOINT_CLIENT_SECRET') or os.getenv('AZURE_AD_CLIENT_SECRET')
            
            if client_id:
                found_vars.append('CLIENT_ID (from SHAREPOINT_CLIENT_ID or AZURE_AD_CLIENT_ID)')
            if tenant_id:
                found_vars.append('TENANT_ID (from SHAREPOINT_TENANT_ID or AZURE_AD_TENANT_ID)')
            if client_secret:
                found_vars.append('CLIENT_SECRET (from SHAREPOINT_CLIENT_SECRET or AZURE_AD_CLIENT_SECRET)')
            
            logging.info(f"Found SharePoint environment variables: {', '.join(found_vars)}")
            
            missing_vars = []
            if not client_id:
                missing_vars.append('CLIENT_ID (SHAREPOINT_CLIENT_ID or AZURE_AD_CLIENT_ID)')
            if not tenant_id:
                missing_vars.append('TENANT_ID (SHAREPOINT_TENANT_ID or AZURE_AD_TENANT_ID)')
            if not client_secret:
                missing_vars.append('CLIENT_SECRET (SHAREPOINT_CLIENT_SECRET or AZURE_AD_CLIENT_SECRET)')
            
            if missing_vars:
                logging.warning(f"Missing SharePoint credentials: {', '.join(missing_vars)}")
    
    if config_path is None:
        config_path = Path(__file__).parent / "config.yaml"
    else:
        config_path = Path(config_path)
    
    config = DEFAULT_CONFIG.copy()
    
    # Load from YAML file if exists
    if config_path.exists():
        try:
            with open(config_path, 'r') as f:
                file_config = yaml.safe_load(f) or {}
                # Deep merge with defaults
                config = _deep_merge(config, file_config)
        except Exception as e:
            print(f"Warning: Failed to load config from {config_path}: {e}")
    
    # Override with environment variables
    config = _load_from_env(config)
    
    return config


def _deep_merge(base: Dict, override: Dict) -> Dict:
    """Deep merge two dictionaries."""
    result = base.copy()
    for key, value in override.items():
        if key in result and isinstance(result[key], dict) and isinstance(value, dict):
            result[key] = _deep_merge(result[key], value)
        else:
            result[key] = value
    return result


def _load_from_env(config: Dict) -> Dict:
    """Load configuration from environment variables."""
    # SharePoint settings
    if os.getenv('SHAREPOINT_ENABLED'):
        config['sharepoint']['enabled'] = os.getenv('SHAREPOINT_ENABLED').lower() == 'true'
    if os.getenv('SHAREPOINT_SITE_URL'):
        config['sharepoint']['site_url'] = os.getenv('SHAREPOINT_SITE_URL')
    if os.getenv('SHAREPOINT_FOLDER_PATH'):
        config['sharepoint']['folder_path'] = os.getenv('SHAREPOINT_FOLDER_PATH')
    if os.getenv('SHAREPOINT_USERNAME'):
        config['sharepoint']['username'] = os.getenv('SHAREPOINT_USERNAME')
    if os.getenv('SHAREPOINT_PASSWORD'):
        config['sharepoint']['password'] = os.getenv('SHAREPOINT_PASSWORD')
    # Check for SHAREPOINT_CLIENT_ID first, fallback to AZURE_AD_CLIENT_ID
    if os.getenv('SHAREPOINT_CLIENT_ID'):
        config['sharepoint']['client_id'] = os.getenv('SHAREPOINT_CLIENT_ID')
    elif os.getenv('AZURE_AD_CLIENT_ID'):
        config['sharepoint']['client_id'] = os.getenv('AZURE_AD_CLIENT_ID')
    
    # Check for SHAREPOINT_CLIENT_SECRET first, fallback to AZURE_AD_CLIENT_SECRET
    if os.getenv('SHAREPOINT_CLIENT_SECRET'):
        config['sharepoint']['client_secret'] = os.getenv('SHAREPOINT_CLIENT_SECRET')
    elif os.getenv('AZURE_AD_CLIENT_SECRET'):
        config['sharepoint']['client_secret'] = os.getenv('AZURE_AD_CLIENT_SECRET')
    
    # Tenant ID (required for Microsoft Graph API)
    if os.getenv('SHAREPOINT_TENANT_ID'):
        config['sharepoint']['tenant_id'] = os.getenv('SHAREPOINT_TENANT_ID')
    elif os.getenv('AZURE_AD_TENANT_ID'):
        config['sharepoint']['tenant_id'] = os.getenv('AZURE_AD_TENANT_ID')
    
    if os.getenv('SHAREPOINT_USE_APP_AUTH'):
        config['sharepoint']['use_app_authentication'] = os.getenv('SHAREPOINT_USE_APP_AUTH').lower() == 'true'
    elif os.getenv('SHAREPOINT_USE_APP_AUTH') is None and os.getenv('AZURE_AD_CLIENT_ID'):
        # If Azure AD credentials are present, default to app auth
        config['sharepoint']['use_app_authentication'] = True
    
    # Scheduler settings
    if os.getenv('SCHEDULER_ENABLED'):
        config['scheduler']['enabled'] = os.getenv('SCHEDULER_ENABLED').lower() == 'true'
    if os.getenv('SCHEDULER_SCHEDULE_TYPE'):
        config['scheduler']['schedule_type'] = os.getenv('SCHEDULER_SCHEDULE_TYPE')
    if os.getenv('SCHEDULER_INTERVAL_HOURS'):
        config['scheduler']['interval_hours'] = int(os.getenv('SCHEDULER_INTERVAL_HOURS'))
    if os.getenv('SCHEDULER_CRON'):
        config['scheduler']['cron_expression'] = os.getenv('SCHEDULER_CRON')
    if os.getenv('SCHEDULER_TIMEZONE'):
        config['scheduler']['timezone'] = os.getenv('SCHEDULER_TIMEZONE')
    
    # API settings
    if os.getenv('API_ENABLED'):
        config['api']['enabled'] = os.getenv('API_ENABLED').lower() == 'true'
    if os.getenv('API_PORT'):
        config['api']['port'] = int(os.getenv('API_PORT'))
    if os.getenv('API_HOST'):
        config['api']['host'] = os.getenv('API_HOST')
    if os.getenv('API_KEY'):
        config['api']['api_key'] = os.getenv('API_KEY')
    
    # Report settings
    if os.getenv('REPORT_OUTPUT_DIR'):
        config['report']['output_dir'] = os.getenv('REPORT_OUTPUT_DIR')
    if os.getenv('REPORT_REPORTS_DIR'):
        config['report']['reports_dir'] = os.getenv('REPORT_REPORTS_DIR')
    
    return config


def save_config_template(config_path: Optional[str] = None) -> None:
    """Save a template configuration file."""
    if config_path is None:
        config_path = Path(__file__).parent / "config.yaml.template"
    else:
        config_path = Path(config_path)
    
    template = """# Vendor Report Generator Configuration

# SharePoint Integration
sharepoint:
  enabled: false  # Set to true to enable SharePoint downloads
  site_url: "https://yourcompany.sharepoint.com/sites/YourSite"
  folder_path: "/Shared Documents/Reports"  # Path to folder containing Excel files
  # file_path: "/Shared Documents/Reports/file.xlsx"  # Alternative: single file path
  local_dir: "reports"  # Local directory to save downloaded files
  username: null  # Username for user authentication (leave null if using app auth)
  password: null  # Password for user authentication (leave null if using app auth)
  client_id: null  # Azure AD app client ID (for app authentication)
  client_secret: null  # Azure AD app client secret (for app authentication)
  use_app_authentication: false  # Set to true to use app authentication (recommended)
  file_pattern: "*.xlsx"  # Pattern to filter files
  overwrite: true  # Whether to overwrite existing files

# Scheduler Configuration
scheduler:
  enabled: false  # Set to true to enable scheduled report generation
  schedule_type: "interval"  # Options: "interval", "cron", or "once"
  interval_hours: 24  # For interval type: generate report every N hours
  cron_expression: "0 8 * * *"  # For cron type: generate at 8 AM daily (cron format)
  timezone: "America/New_York"  # Timezone for scheduling

# API Configuration (for on-demand report generation)
api:
  enabled: false  # Set to true to enable web API
  host: "0.0.0.0"  # Host to bind API server
  port: 8080  # Port for API server
  api_key: null  # Optional API key for authentication (set to enable auth)

# Report Settings
report:
  output_dir: "output"  # Directory for generated reports
  reports_dir: "reports"  # Directory containing Excel files
"""
    
    with open(config_path, 'w') as f:
        f.write(template)
    
    print(f"Configuration template saved to: {config_path}")

