#!/usr/bin/env python3
"""
StellarMate OS Integrity Check - Main Script
Performs comprehensive file integrity checking on system startup.
"""

import os
import sys
import json
import socket
from pathlib import Path

# Try importing from installed package first, fall back to local development
try:
    from stellarmate_integrity import (
        IntegrityLogger,
        ChecksumCalculator,
        RecoveryManager,
        FileChecker
    )
except ImportError:
    # Development mode: add parent directory to path for local imports
    sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
    from core import (
        IntegrityLogger,
        ChecksumCalculator,
        RecoveryManager,
        FileChecker
    )


class IntegrityCheckOrchestrator:
    """
    Main orchestrator for the integrity check system.
    Loads configuration, manages checking process, and reports results.
    """
    
    VERSION = "1.0.0"
    
    def __init__(self, config_dir: str = '/usr/share/stellarmate/integrity'):
        """
        Initialize the orchestrator.
        
        Args:
            config_dir: Directory containing configuration files
        """
        self.config_dir = config_dir
        self.model = self._detect_model()
        self.hostname = socket.gethostname()
        
        # Initialize components
        self.logger = IntegrityLogger()
        self.checksum = ChecksumCalculator()
        self.recovery = RecoveryManager()
        self.checker = FileChecker(
            self.logger, self.recovery, self.checksum, self.hostname, self.model
        )
        
        # Configuration
        self.files_config = []
        self.manifest = {}
    
    def _detect_model(self) -> str:
        """Detect the system model."""
        model_file = '/etc/stellarmate/model'
        if os.path.exists(model_file):
            try:
                with open(model_file, 'r') as f:
                    return f.read().strip()
            except Exception:
                pass
        return "SM-170"  # Default
    
    def load_configuration(self) -> bool:
        """Load files configuration and manifest."""
        # Load files configuration
        files_config_path = os.path.join(self.config_dir, 'files_config.json')
        if not os.path.exists(files_config_path):
            self.logger.error(f"Configuration file not found: {files_config_path}")
            return False
        
        try:
            with open(files_config_path, 'r') as f:
                all_files = json.load(f)
            
            # Filter by model and expand variables
            self.files_config = []
            for f in all_files:
                if 'models' not in f or self.model in f.get('models', []):
                    # Expand {HOSTNAME} in file_path
                    if 'file_path' in f and '{HOSTNAME}' in f['file_path']:
                        f = f.copy()
                        f['file_path'] = f['file_path'].replace('{HOSTNAME}', self.hostname)
                    self.files_config.append(f)
            
            self.logger.info(f"Loaded {len(self.files_config)} file configurations for model {self.model}")
            
        except Exception as e:
            self.logger.error(f"Failed to load files configuration: {e}")
            return False
        
        # Load SHA256 manifest
        manifest_path = os.path.join(self.config_dir, 'checksums.json')
        if os.path.exists(manifest_path):
            try:
                with open(manifest_path, 'r') as f:
                    manifest_data = json.load(f)
                
                # Convert to lookup dict
                self.manifest = {
                    entry['file_path']: entry
                    for entry in manifest_data.get('files', [])
                }
                
                self.logger.info(f"Loaded {len(self.manifest)} SHA256 checksums")
                
            except Exception as e:
                self.logger.warning(f"Failed to load checksum manifest: {e}")
        else:
            self.logger.warning(f"Checksum manifest not found at {manifest_path}")
        
        return True
    
    def run_checks(self) -> dict:
        """
        Run integrity checks on all configured files.
        
        Returns:
            Statistics dictionary
        """
        self.logger.log_start(self.VERSION, self.model)
        
        if not self.files_config:
            self.logger.error("No files to check")
            return self.logger.log_finish()
        
        # Check each file
        for file_config in self.files_config:
            file_path = file_config.get('file_path', '')
            manifest_entry = self.manifest.get(file_path)
            
            try:
                self.checker.check_file(file_config, manifest_entry)
            except Exception as e:
                self.logger.log_error(file_path, f"Unexpected error: {e}")
        
        # Clean up old backups (keep last 30 days)
        deleted = self.recovery.cleanup_old_backups(days=30)
        if deleted > 0:
            self.logger.info(f"Cleaned up {deleted} old backup files")
        
        # Log final statistics
        stats = self.logger.log_finish()
        
        return stats
    
    def run(self) -> int:
        """
        Main entry point for the integrity check.
        
        Returns:
            Exit code (0 for success, 1 for failure)
        """
        try:
            # Load configuration
            if not self.load_configuration():
                return 1
            
            # Run checks
            stats = self.run_checks()
            
            # Return success even if some checks failed (auto-repair mode)
            # Only return error if we couldn't load config or critical system error
            return 0
            
        except KeyboardInterrupt:
            self.logger.warning("Interrupted by user")
            return 130
        except Exception as e:
            self.logger.critical(f"Fatal error: {e}")
            return 1


def main():
    """Main function."""
    # Check if running as root
    if os.geteuid() != 0:
        print("WARNING: This script should be run as root for full functionality")
    
    # Create orchestrator and run
    orchestrator = IntegrityCheckOrchestrator()
    exit_code = orchestrator.run()
    
    sys.exit(exit_code)


if __name__ == '__main__':
    main()
