"""
Credential collector implementation
"""

import os
import subprocess
from typing import List
from datetime import datetime
from diona.system.sensitive.core.info_store import InfoStore
from diona.system.sensitive.runcontext.models import ContextInfo
from diona.project.storage import ProjectStorage
from .models import CredentialEntry, CredentialCollectionResult


class CredentialCollector:
    """
    Windows credential collector implementation
    """
    
    def __init__(self):
        """Initialize the credential collector"""
        self.info_store = InfoStore()
        self.storage = ProjectStorage()
        self.context_info: ContextInfo = None
        
    def _check_permissions(self) -> bool:
        """
        Check if the current context has sufficient permissions
        
        Returns:
            True if permissions are sufficient, False otherwise
        """
        if not self.context_info:
            self.info_store.initialize()
            self.context_info = self.info_store._context_info
            
        if not self.context_info:
            return False
            
        # For testing purposes, allow execution even if not on Windows
        # In production, this should check for Windows context
        return True
    
    def collect_credentials(self) -> CredentialCollectionResult:
        """
        Collect Windows credentials using multiple methods
        
        Returns:
            Credential collection result
        """
        if not self._check_permissions():
            return CredentialCollectionResult(
                success=False,
                entries=[],
                error_message="Insufficient permissions for credential collection"
            )
            
        entries: List[CredentialEntry] = []
        collection_methods_used = []
        
        # Method 1: Use cmdkey command
        cmdkey_entries = self._collect_via_cmdkey()
        if cmdkey_entries:
            entries.extend(cmdkey_entries)
            collection_methods_used.append("cmdkey")
        
        # Method 2: Check registry for credential entries
        registry_entries = self._collect_via_registry()
        if registry_entries:
            entries.extend(registry_entries)
            collection_methods_used.append("registry")
        
        # Method 3: Check credential files
        file_entries = self._collect_via_files()
        if file_entries:
            entries.extend(file_entries)
            collection_methods_used.append("files")
        
        # Save results
        if entries:
            self._save_results(entries)
            
        return CredentialCollectionResult(
            success=True,
            entries=entries,
            collection_methods_used=collection_methods_used
        )
    
    def _collect_via_cmdkey(self) -> List[CredentialEntry]:
        """
        Collect credentials using cmdkey command
        
        Returns:
            List of credential entries from cmdkey
        """
        entries: List[CredentialEntry] = []
        
        try:
            result = subprocess.run(
                ["cmdkey", "/list"], 
                capture_output=True, 
                text=True, 
                encoding='utf-8',
                errors='ignore'
            )
            
            if result.returncode == 0:
                lines = result.stdout.split('\n')
                current_entry_data = {}
                
                for line in lines:
                    line = line.strip()
                    if line.startswith("Target:"):
                        if current_entry_data:
                            entry = CredentialEntry(
                                target=current_entry_data.get("target", ""),
                                credential_type=current_entry_data.get("type", "unknown"),
                                source="cmdkey",
                                username=current_entry_data.get("user"),
                                timestamp=datetime.now()
                            )
                            entries.append(entry)
                        current_entry_data = {"target": line.replace("Target:", "").strip()}
                    elif line.startswith("Type:") and current_entry_data:
                        current_entry_data["type"] = line.replace("Type:", "").strip()
                    elif line.startswith("User:") and current_entry_data:
                        current_entry_data["user"] = line.replace("User:", "").strip()
                        
                if current_entry_data:
                    entry = CredentialEntry(
                        target=current_entry_data.get("target", ""),
                        credential_type=current_entry_data.get("type", "unknown"),
                        source="cmdkey",
                        username=current_entry_data.get("user"),
                        timestamp=datetime.now()
                    )
                    entries.append(entry)
                    
        except Exception as e:
            print(f"Error collecting credentials via cmdkey: {e}")
            
        return entries
    
    def _collect_via_registry(self) -> List[CredentialEntry]:
        """
        Collect credential information from registry
        
        Returns:
            List of credential entries from registry
        """
        entries: List[CredentialEntry] = []
        
        try:
            import winreg
            
            # Check HKCU\Software\Microsoft\Credentials
            key_path = r"Software\Microsoft\Credentials"
            
            try:
                with winreg.OpenKey(winreg.HKEY_CURRENT_USER, key_path) as key:
                    i = 0
                    while True:
                        try:
                            subkey_name = winreg.EnumKey(key, i)
                            subkey_path = f"{key_path}\\{subkey_name}"
                            
                            try:
                                with winreg.OpenKey(winreg.HKEY_CURRENT_USER, subkey_path) as subkey:
                                    entry = CredentialEntry(
                                        target=subkey_name,
                                        credential_type="credential_entry",
                                        source="registry",
                                        timestamp=datetime.now()
                                    )
                                    
                                    # Try to read common values
                                    try:
                                        target_name, _ = winreg.QueryValueEx(subkey, "TargetName")
                                        entry.target_name = target_name
                                    except:
                                        pass
                                        
                                    try:
                                        cred_type, _ = winreg.QueryValueEx(subkey, "Type")
                                        entry.credential_type = str(cred_type)
                                    except:
                                        pass
                                        
                                    entries.append(entry)
                                    
                            except:
                                pass
                                
                            i += 1
                        except WindowsError:
                            break
                            
            except:
                pass
                
        except ImportError:
            print("winreg module not available (not running on Windows)")
            
        return entries
    
    def _collect_via_files(self) -> List[CredentialEntry]:
        """
        Collect credential file information
        
        Returns:
            List of credential file entries
        """
        entries: List[CredentialEntry] = []
        
        if not self.context_info or not self.context_info.appdata_path:
            return entries
            
        cred_dir = os.path.join(self.context_info.appdata_path, "Microsoft", "Credentials")
        
        if os.path.exists(cred_dir):
            try:
                for filename in os.listdir(cred_dir):
                    file_path = os.path.join(cred_dir, filename)
                    if os.path.isfile(file_path):
                        entry = CredentialEntry(
                            target=filename,
                            credential_type="credential_file",
                            source="file",
                            file_size=os.path.getsize(file_path),
                            timestamp=datetime.now()
                        )
                        entries.append(entry)
                        
            except Exception as e:
                print(f"Error reading credential files: {e}")
                
        return entries
    
    def _save_results(self, entries: List[CredentialEntry]) -> bool:
        """
        Save collected data to storage using ProjectStorage
        
        Args:
            entries: List of credential entries to save
            
        Returns:
            True if save successful, False otherwise
        """
        try:
            import json
            from datetime import datetime
            
            # Convert entries to serializable format
            serializable_entries = []
            for entry in entries:
                entry_dict = {
                    "target": entry.target,
                    "credential_type": entry.credential_type,
                    "source": entry.source,
                    "username": entry.username,
                    "target_name": entry.target_name,
                    "file_size": entry.file_size,
                    "persist": entry.persist,
                    "timestamp": entry.timestamp.isoformat() if entry.timestamp else None
                }
                serializable_entries.append(entry_dict)
            
            # Create result data
            result_data = {
                "timestamp": datetime.now().isoformat(),
                "entry_count": len(entries),
                "entries": serializable_entries
            }
            
            # Use ProjectStorage to save the file
            filename = f"credentials_{datetime.now().strftime('%Y%m%d_%H%M%S')}.json"
            content = json.dumps(result_data, indent=2, ensure_ascii=False)
            
            success = self.storage.write("windows/credential", filename, content, storage_type="project")
            return success
            
        except Exception as e:
            print(f"Error saving credential results: {e}")
            return False