"""Process scanner for finding game executables — now using psutil with fuzzy matching."""
import sys
import re
import logging

logger = logging.getLogger('SweetCheat.ProcessScanner')
WINDOWS = sys.platform == 'win32'

psutil = None
if WINDOWS:
    try:
        import psutil
    except ImportError:
        psutil = None


class ProcessScanner:
    def __init__(self):
        self.known_games = {
            'stardew-valley': ['Stardew Valley.exe', 'StardewModdingAPI.exe', 'StardewValley.exe'],
            'witcher-3':      ['witcher3.exe'],
            'cyberpunk-2077': ['Cyberpunk2077.exe'],
            'gta-v':          ['GTA5.exe', 'GTAIV.exe'],
            'minecraft-java': ['javaw.exe', 'java.exe'],
        }

    def list_all(self):
        """Return all running process names."""
        out = []
        if not WINDOWS or not psutil:
            return out
        try:
            for proc in psutil.process_iter(['name']):
                out.append(proc.info.get('name') or '')
        except Exception as e:
            logger.error(f"list_all failed: {e}")
        return out

    def find_by_name(self, process_name):
        """Find a process by exact name (case-insensitive)."""
        if not WINDOWS or not psutil:
            return None
        try:
            for proc in psutil.process_iter(['pid', 'name', 'exe']):
                name = proc.info.get('name') or ''
                if name.lower() == process_name.lower():
                    return {'pid': proc.info.get('pid'), 'name': name, 'exe': proc.info.get('exe') or ''}
        except Exception as e:
            logger.error(f"find_by_name error: {e}")
        return None

    def find_by_keyword(self, keyword):
        """Find first process whose name contains the keyword."""
        if not WINDOWS or not psutil:
            return None
        keyword = keyword.lower()
        try:
            for proc in psutil.process_iter(['pid', 'name', 'exe']):
                name = proc.info.get('name') or ''
                if keyword in name.lower():
                    return {'pid': proc.info.get('pid'), 'name': name, 'exe': proc.info.get('exe') or ''}
        except Exception as e:
            logger.error(f"find_by_keyword error: {e}")
        return None

    def scan_for_game(self, slug, extra_names=None):
        """Try to detect a running process for a given game slug or list of process names."""
        names = []
        if slug in self.known_games:
            names = list(self.known_games[slug])
        if extra_names:
            names.extend(extra_names)
        if not names:
            return None

        # 1. Exact
        for n in names:
            hit = self.find_by_name(n)
            if hit:
                return hit
        # 2. Fuzzy by base keyword of each candidate
        for n in names:
            base = re.split(r'[.\s]', n)[0].lower()
            if len(base) < 3:
                continue
            hit = self.find_by_keyword(base)
            if hit:
                return hit
        return None


if __name__ == '__main__' and WINDOWS:
    scanner = ProcessScanner()
    print('All processes:', scanner.list_all()[:20])
    print('Stardew:', scanner.scan_for_game('stardew-valley'))
