#!/usr/bin/env python3
"""
Enhanced detector with DONE.md and LLM-optimized TODO.md generation
"""

import configparser
import datetime
import fnmatch
import json
import logging
import re
import stat
import subprocess
from pathlib import Path
from typing import Dict, List, Optional, Set

try:
    import toml
except ImportError:
    toml = None

logger = logging.getLogger(__name__)


class DomdIgnoreParser:
    """Parser for .doignore file."""

    def __init__(self, ignore_file_path: Path):
        self.ignore_file_path = ignore_file_path
        self.ignore_patterns: List[str] = []
        self.exact_matches: Set[str] = set()
        self._load_ignore_file()

    def _load_ignore_file(self) -> None:
        """Load and parse .doignore file."""
        if not self.ignore_file_path.exists():
            logger.info(f"No .doignore file found at {self.ignore_file_path}")
            return

        try:
            with open(self.ignore_file_path, "r", encoding="utf-8") as f:
                lines = f.readlines()

            for line_num, line in enumerate(lines, 1):
                line = line.strip()

                if not line or line.startswith("#"):
                    continue

                if "*" in line or "?" in line or "[" in line:
                    self.ignore_patterns.append(line)
                    logger.debug(f"Added ignore pattern: {line}")
                else:
                    self.exact_matches.add(line)
                    logger.debug(f"Added exact ignore match: {line}")

            total_rules = len(self.ignore_patterns) + len(self.exact_matches)
            logger.info(
                f"Loaded {total_rules} ignore rules from {self.ignore_file_path}"
            )

        except Exception as e:
            logger.error(f"Error loading .doignore file: {e}")

    def should_ignore_command(self, command: str) -> bool:
        """Check if a command should be ignored."""
        command_clean = command.strip()

        if command_clean in self.exact_matches:
            return True

        for pattern in self.ignore_patterns:
            if fnmatch.fnmatch(command_clean, pattern):
                return True

        return False

    def get_ignore_reason(self, command: str) -> Optional[str]:
        """Get the reason why a command is ignored."""
        command_clean = command.strip()

        if command_clean in self.exact_matches:
            return f"exact match: {command_clean}"

        for pattern in self.ignore_patterns:
            if fnmatch.fnmatch(command_clean, pattern):
                return f"pattern match: {pattern}"

        return None


class ProjectCommandDetector:
    """Enhanced detector with DONE.md and LLM-optimized TODO.md."""

    def __init__(
        self,
        project_path: str = ".",
        timeout: int = 60,
        exclude_patterns: List[str] = None,
        include_patterns: List[str] = None,
        todo_file: str = "TODO.md",
        done_file: str = "DONE.md",
        script_file: str = "todo.sh",
        ignore_file: str = ".doignore",
    ):
        """Initialize the detector with DONE.md support."""
        self.project_path = Path(project_path).resolve()
        self.timeout = timeout
        self.exclude_patterns = exclude_patterns or []
        self.include_patterns = include_patterns or []
        self.failed_commands = []
        self.successful_commands = []
        self.ignored_commands = []
        self.todo_file = Path(todo_file)
        self.done_file = Path(done_file)
        self.script_file = Path(script_file)

        # Initialize ignore parser
        ignore_file_path = self.project_path / ignore_file
        self.ignore_parser = DomdIgnoreParser(ignore_file_path)

        # Configuration files mapping (using method names as strings to avoid reference issues)
        self.config_files = {
            "package.json": "_parse_package_json",
            "pyproject.toml": "_parse_pyproject_toml",
            "Makefile": "_parse_makefile",
            "makefile": "_parse_makefile",
            "tox.ini": "_parse_tox_ini",
            "pytest.ini": "_parse_pytest_ini",
            "requirements.txt": "_check_pip_install",
            "setup.py": "_parse_setup_py",
            "Dockerfile": "_parse_dockerfile",
            "docker-compose.yml": "_parse_docker_compose",
            "docker-compose.yaml": "_parse_docker_compose",
            "CMakeLists.txt": "_parse_cmake",
            "composer.json": "_parse_composer_json",
            "Gemfile": "_parse_gemfile",
            "Cargo.toml": "_parse_cargo_toml",
            "go.mod": "_check_go_commands",
        }

    def create_done_md(self):
        """Create DONE.md with all successful commands."""
        if not self.successful_commands:
            logger.info("No successful commands to write to DONE.md")
            return

        content = [
            "# ✅ DONE - Successfully Working Commands",
            "",
            "**🎉 Generated by TodoMD** - List of all working project commands",
            f"**Last Updated:** {datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}",
            f"**Project:** {self.project_path}",
            f"**Total Working Commands:** {len(self.successful_commands)}",
            "",
            "---",
            "",
            "## 📊 Summary",
            "",
            f"✅ **{len(self.successful_commands)} commands are working correctly**",
            "",
            "These commands have been tested and are functioning properly.",
            "You can safely use them in your development workflow.",
            "",
            "---",
            "",
            "## 🟢 Working Commands",
            "",
        ]

        # Group commands by source for better organization
        by_source = {}
        for cmd in self.successful_commands:
            source = cmd["source"]
            if source not in by_source:
                by_source[source] = []
            by_source[source].append(cmd)

        for source, source_commands in sorted(by_source.items()):
            content.extend([f"### 📄 From {source}", ""])

            for cmd in source_commands:
                execution_time = cmd.get("execution_time", 0)
                content.extend(
                    [
                        f"#### ✅ {cmd['description']}",
                        "",
                        f"**Command:** `{cmd['command']}`",
                        f"**Execution Time:** {execution_time:.2f}s",
                        f"**Type:** {cmd.get('type', 'unknown')}",
                        "",
                        "**Status:** 🟢 **WORKING**",
                        "",
                        "---",
                        "",
                    ]
                )

        content.extend(
            [
                "",
                "## 🔄 Updating This File",
                "",
                "This file is automatically updated when commands are tested.",
                "To refresh the status:",
                "",
                "1. Run: `domd` to test all commands",
                "2. Working commands will appear here",
                "3. Failed commands will be moved to TODO.md for fixing",
                "",
                f"**Last test run:** {datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}",
                "",
            ]
        )

        # Write to file
        with open(self.done_file, "w", encoding="utf-8") as f:
            f.write("\n".join(content))

        logger.info(
            f"Created {self.done_file} with {len(self.successful_commands)} successful commands"
        )

    def create_llm_optimized_todo_md(self):
        """Create LLM-optimized TODO.md with detailed fix instructions."""
        content = [
            "# 🤖 TODO - LLM Task List for Command Fixes",
            "",
            "**📋 INSTRUCTIONS FOR LLM:**",
            "This file contains a list of broken commands that need to be fixed.",
            "Each task is a separate command that failed during testing.",
            "",
            "**🎯 YOUR MISSION:**",
            "1. **Analyze each failed command** and its error output",
            "2. **Identify the root cause** of the failure",
            "3. **Implement the fix** by modifying source code, config files, or dependencies",
            "4. **Test the fix** by running the command manually",
            "5. **Update progress** - when a command starts working, it will be moved to DONE.md automatically",
            "",
            "**📝 TASK FORMAT:**",
            "Each task has:",
            "- ❌ **Command** that failed",
            "- 📁 **Source file** where the command is defined",
            "- 🔴 **Error output** with full details",
            "- 💡 **Suggested actions** for fixing",
            "",
            "**🔄 WORKFLOW:**",
            "1. Pick a task from the list below",
            "2. Read the error details carefully",
            "3. Implement the fix",
            "4. Run `domd` to retest all commands",
            "5. Fixed commands will automatically move to DONE.md",
            "",
            "---",
            "",
            "**📊 Current Status:**",
            f"- **Failed Commands:** {len(self.failed_commands)}",
            f"- **Working Commands:** {len(self.successful_commands)} (see DONE.md)",
            f"- **Last Updated:** {datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}",
            "",
            "---",
            "",
        ]

        if not self.failed_commands:
            content.extend(
                [
                    "## 🎉 All Commands Working!",
                    "",
                    "✅ **No failed commands found!**",
                    "",
                    "All project commands are working correctly.",
                    f"Check {self.done_file} for the list of working commands.",
                    "",
                ]
            )
        else:
            content.extend(
                [
                    f"## 🔧 Tasks to Fix ({len(self.failed_commands)} commands)",
                    "",
                    "Each section below is a separate task. Fix them one by one:",
                    "",
                ]
            )

            for i, cmd in enumerate(self.failed_commands, 1):
                content.extend(
                    [
                        f"### [ ] Task {i}: {cmd['description']}",
                        "",
                        f"**📋 Command:** `{cmd['command']}`",
                        f"**📁 Source:** `{cmd['source']}`",
                        f"**⏱️ Timeout:** {self.timeout}s",
                        f"**🔴 Return Code:** {cmd.get('return_code', 'N/A')}",
                        f"**⚡ Execution Time:** {cmd.get('execution_time', 0):.2f}s",
                        "",
                        "#### 🔴 Error Output:",
                        "",
                        "```bash",
                        "# Command that failed:",
                        cmd["command"],
                        "",
                        "# Error output:",
                        cmd.get("error", "No error output captured"),
                        "```",
                        "",
                        "#### 💡 Suggested Fix Actions:",
                        "",
                    ]
                )

                # Generate specific suggestions based on error type
                suggestions = self._generate_fix_suggestions(cmd)
                for suggestion in suggestions:
                    content.append(f"- [ ] {suggestion}")

                content.extend(
                    [
                        "",
                        "#### 🔍 Investigation Steps:",
                        "",
                        f"1. **Check source file:** Open `{cmd['source']}` and locate the command definition",
                        "2. **Analyze error:** Read the error output above for clues",
                        "3. **Check dependencies:** Verify all required tools/packages are installed",
                        f"4. **Test manually:** Run `{cmd['command']}` in terminal to reproduce the issue",
                        "5. **Implement fix:** Based on error analysis, modify files as needed",
                        "6. **Verify fix:** Run the command again to confirm it works",
                        "",
                        "#### ✅ Completion Criteria:",
                        "",
                        f"This task is complete when `{cmd['command']}` runs without errors.",
                        "The command will then automatically appear in DONE.md on the next test run.",
                        "",
                        "---",
                        "",
                    ]
                )

        content.extend(
            [
                "",
                "## 🔄 After Making Fixes",
                "",
                "When you've fixed one or more commands:",
                "",
                "1. **Test your fixes:**",
                "   ```bash",
                "   # Test specific command manually:",
                f"   cd {self.project_path}",
                "   [your-fixed-command]",
                "   ",
                "   # Or test all commands:",
                "   domd",
                "   ```",
                "",
                "2. **Check results:**",
                "   - Fixed commands → will appear in DONE.md",
                "   - Still broken commands → remain in this TODO.md",
                "   - New failures → will be added to this TODO.md",
                "",
                "3. **Iterate:**",
                "   - Continue fixing remaining tasks",
                "   - Re-run `domd` after each fix",
                "   - Monitor progress in both files",
                "",
                "## 📚 Common Fix Patterns",
                "",
                "### Missing Dependencies",
                "```bash",
                "# Python",
                "pip install missing-package",
                "poetry add missing-package",
                "",
                "# Node.js",
                "npm install missing-package",
                "yarn add missing-package",
                "",
                "# System",
                "sudo apt install missing-tool",
                "brew install missing-tool",
                "```",
                "",
                "### Configuration Issues",
                "```bash",
                "# Check config files for typos",
                "# Verify paths and settings",
                "# Update outdated configurations",
                "```",
                "",
                "### Permission Issues",
                "```bash",
                "chmod +x script-file",
                "sudo chown user:group file",
                "```",
                "",
                "### Version Compatibility",
                "```bash",
                "# Update to compatible versions",
                "# Check tool documentation",
                "# Use version-specific commands",
                "```",
                "",
            ]
        )

        # Write to file
        with open(self.todo_file, "w", encoding="utf-8") as f:
            f.write("\n".join(content))

        logger.info(
            f"Created LLM-optimized {self.todo_file} with {len(self.failed_commands)} tasks"
        )

    def _generate_fix_suggestions(self, cmd: Dict) -> List[str]:
        """Generate specific fix suggestions based on command and error."""
        suggestions = []
        command = cmd["command"]
        error = cmd.get("error", "").lower()
        source = cmd.get("source", "")
        cmd_type = cmd.get("type", "")

        # Common patterns
        if "command not found" in error or "not found" in error:
            suggestions.extend(
                [
                    "Install missing tool/command: Look for installation instructions",
                    f"Check if command is in PATH: `which {command.split()[0]}`",
                    f"Verify spelling of command in {source}",
                ]
            )

        elif "permission denied" in error:
            suggestions.extend(
                [
                    "Fix file permissions: `chmod +x` for executable files",
                    "Check directory permissions for write access",
                    "Run with appropriate user privileges if needed",
                ]
            )

        elif "no such file" in error or "file not found" in error:
            suggestions.extend(
                [
                    "Check if referenced files exist in the project",
                    f"Verify file paths in {source} are correct",
                    "Create missing files or update paths",
                ]
            )

        elif "timeout" in error or cmd.get("return_code") == -1:
            suggestions.extend(
                [
                    f"Command took longer than {self.timeout}s - consider increasing timeout",
                    "Check if command is hanging or waiting for input",
                    "Add to .doignore if this is a long-running service command",
                ]
            )

        # Type-specific suggestions
        if cmd_type == "npm_script":
            suggestions.extend(
                [
                    "Run `npm install` to ensure all dependencies are installed",
                    "Check package.json for script definition errors",
                    "Verify Node.js and npm versions are compatible",
                ]
            )

        elif cmd_type == "poetry_script":
            suggestions.extend(
                [
                    "Run `poetry install` to install dependencies",
                    "Check pyproject.toml for script configuration",
                    "Verify poetry is installed and accessible",
                ]
            )

        elif cmd_type == "make_target":
            suggestions.extend(
                [
                    "Check Makefile syntax and dependencies",
                    "Verify all required tools are installed (gcc, etc.)",
                    "Check if target dependencies exist",
                ]
            )

        elif cmd_type == "pytest":
            suggestions.extend(
                [
                    "Install pytest: `pip install pytest`",
                    "Check test file syntax and imports",
                    "Verify test configuration in pytest.ini or pyproject.toml",
                ]
            )

        elif cmd_type == "tox_env":
            suggestions.extend(
                [
                    "Install tox: `pip install tox`",
                    "Check tox.ini configuration",
                    "Verify Python versions are available",
                ]
            )

        elif "docker" in cmd_type:
            suggestions.extend(
                [
                    "Check if Docker is running: `docker --version`",
                    "Verify Dockerfile syntax",
                    "Check Docker permissions for current user",
                ]
            )

        # Generic fallbacks
        if not suggestions:
            suggestions.extend(
                [
                    "Read the error output carefully for specific clues",
                    f"Check {source} for command definition and syntax",
                    "Manually run the command to reproduce and debug the issue",
                    "Search for similar errors online or in documentation",
                    "Consider if this command should be added to .doignore",
                ]
            )

        return suggestions

    def scan_and_initialize(self) -> List[Dict]:
        """Scan project, filter commands, and create initial files."""
        print(f"🔍 Scanning project: {self.project_path}")

        # Check if .doignore exists
        ignore_file_path = self.project_path / ".doignore"
        if ignore_file_path.exists():
            print("📋 Found .doignore file with ignore rules")
        else:
            print("💡 No .doignore file found - create one to skip specific commands")

        # Scan for all commands
        all_commands = self.scan_project()

        if not all_commands:
            print("❌ No commands found to test.")
            return []

        # Filter commands through .doignore
        filtered_commands = []
        for cmd in all_commands:
            if self.ignore_parser.should_ignore_command(cmd["command"]):
                reason = self.ignore_parser.get_ignore_reason(cmd["command"])
                cmd["ignore_reason"] = reason
                self.ignored_commands.append(cmd)
                logger.info(f"Ignoring command: {cmd['command']} ({reason})")
            else:
                filtered_commands.append(cmd)

        # Report filtering results
        total_found = len(all_commands)
        total_ignored = len(self.ignored_commands)
        total_to_test = len(filtered_commands)

        print(f"✅ Found {total_found} total commands")
        if total_ignored > 0:
            print(f"🚫 Ignored {total_ignored} commands (via .doignore)")
        print(f"🧪 Will test {total_to_test} commands")

        if not filtered_commands:
            print("⚠️  No commands to test after filtering!")
            return []

        # Create initial files
        self._create_initial_status_files(filtered_commands, all_commands)
        self._create_todo_script(filtered_commands)

        print(f"📝 Created {self.todo_file} (LLM task list)")
        print(f"✅ Created {self.done_file} (working commands)")
        print(f"🔧 Created {self.script_file} (executable script)")

        return filtered_commands

    def _create_initial_status_files(
        self, commands_to_test: List[Dict], all_commands: List[Dict]
    ):
        """Create initial TODO.md and DONE.md files."""
        # Create initial TODO.md with pending tasks
        content = [
            "# 🤖 TODO - LLM Task List for Command Fixes",
            "",
            "**📋 INSTRUCTIONS FOR LLM:**",
            "This file will be populated with failed commands after testing.",
            "Commands are currently being scanned and will be tested shortly.",
            "",
            "**📊 Scan Results:**",
            f"- **Total Commands Found:** {len(all_commands)}",
            f"- **Commands to Test:** {len(commands_to_test)}",
            f"- **Commands Ignored:** {len(self.ignored_commands)} (via .doignore)",
            "",
            "**⏳ Status:** Ready for testing",
            "",
            "Run `domd` to test all commands and populate this file with specific tasks.",
            "",
        ]

        with open(self.todo_file, "w", encoding="utf-8") as f:
            f.write("\n".join(content))

        # Create initial empty DONE.md
        done_content = [
            "# ✅ DONE - Successfully Working Commands",
            "",
            "**🎉 Generated by TodoMD** - List of all working project commands",
            f"**Last Updated:** {datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}",
            f"**Project:** {self.project_path}",
            "",
            "**⏳ Status:** Commands not yet tested",
            "",
            "This file will be populated with working commands after testing.",
            "Run `domd` to test all commands and see results here.",
            "",
        ]

        with open(self.done_file, "w", encoding="utf-8") as f:
            f.write("\n".join(done_content))

    def test_commands(self, commands: List[Dict]) -> None:
        """Test commands and update both TODO.md and DONE.md."""
        logger.info(f"Testing {len(commands)} commands (after .doignore filtering)")

        for i, cmd_info in enumerate(commands, 1):
            logger.info(f"[{i}/{len(commands)}] Testing: {cmd_info['description']}")

            success = self._execute_command(cmd_info)

            if success:
                self.successful_commands.append(cmd_info)
                logger.info(f"✅ Command succeeded: {cmd_info['description']}")
            else:
                self.failed_commands.append(cmd_info)
                logger.warning(f"❌ Command failed: {cmd_info['description']}")

        # Generate final files
        self.create_llm_optimized_todo_md()
        self.create_done_md()

        # Print summary
        print("\n📊 Test Results:")
        print(f"   ✅ Working: {len(self.successful_commands)} → {self.done_file}")
        print(f"   ❌ Failed: {len(self.failed_commands)} → {self.todo_file}")
        print(f"   🚫 Ignored: {len(self.ignored_commands)} (via .doignore)")

    def _create_todo_script(self, commands: List[Dict]):
        """Create executable todo.sh script."""
        if not commands:
            return

        script_content = [
            "#!/bin/bash",
            "# TodoMD Generated Script",
            f"# Created: {datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}",
            f"# Project: {self.project_path}",
            f"# Commands to Test: {len(commands)}",
            "",
            "set -e",
            "",
            "TOTAL_COMMANDS=" + str(len(commands)),
            "SUCCESSFUL=0",
            "FAILED=0",
            "CURRENT=0",
            "",
            "run_command() {",
            '    local cmd="$1"',
            '    local desc="$2"',
            "    ((CURRENT++))",
            "    echo",
            '    echo "[${CURRENT}/${TOTAL_COMMANDS}] Testing: $desc"',
            '    echo "Command: $cmd"',
            '    if timeout 60 bash -c "$cmd"; then',
            '        echo "✅ SUCCESS"',
            "        ((SUCCESSFUL++))",
            "    else",
            '        echo "❌ FAILED"',
            "        ((FAILED++))",
            "    fi",
            "}",
            "",
            'echo "TodoMD Test Script"',
            'echo "=================="',
            f'echo "Commands to test: {len(commands)}"',
            f'echo "Ignored commands: {len(self.ignored_commands)}"',
            "echo",
            "",
        ]

        for i, cmd in enumerate(commands, 1):
            escaped_cmd = cmd["command"].replace('"', '\\"')
            script_content.extend(
                [
                    f"run_command \"{escaped_cmd}\" \"{cmd['description']}\"",
                ]
            )

        script_content.extend(
            [
                "",
                "echo",
                'echo "=================="',
                'echo "SUMMARY"',
                'echo "=================="',
                'echo "Successful: $SUCCESSFUL"',
                'echo "Failed: $FAILED"',
                'echo "Total: $TOTAL_COMMANDS"',
            ]
        )

        with open(self.script_file, "w", encoding="utf-8") as f:
            f.write("\n".join(script_content))

        self.script_file.chmod(self.script_file.stat().st_mode | stat.S_IEXEC)

    def _execute_command(self, cmd_info: Dict) -> bool:
        """Execute a single command."""
        try:
            start_time = datetime.datetime.now()

            result = subprocess.run(
                cmd_info["command"],
                shell=True,
                cwd=self.project_path,
                capture_output=True,
                text=True,
                timeout=self.timeout,
            )

            end_time = datetime.datetime.now()
            cmd_info["execution_time"] = (end_time - start_time).total_seconds()

            if result.returncode == 0:
                return True
            else:
                cmd_info["error"] = result.stderr or result.stdout
                cmd_info["return_code"] = result.returncode
                return False

        except subprocess.TimeoutExpired:
            cmd_info["error"] = f"Command timed out after {self.timeout} seconds"
            cmd_info["return_code"] = -1
            cmd_info["execution_time"] = self.timeout
            return False
        except Exception as e:
            cmd_info["error"] = str(e)
            cmd_info["return_code"] = -2
            cmd_info["execution_time"] = 0
            return False

    def scan_project(self) -> List[Dict]:
        """Scan project for configuration files and extract commands."""
        logger.info(f"Scanning project: {self.project_path}")

        found_files = []
        commands_to_test = []

        for config_file, parser_name in self.config_files.items():
            file_path = self.project_path / config_file
            if file_path.exists() and self._should_process_file(file_path):
                found_files.append(file_path)
                try:
                    # Get the parser method by name
                    parser_func = getattr(self, parser_name, None)
                    if parser_func is None:
                        logger.error(
                            f"Parser method {parser_name} not found for {file_path}"
                        )
                        continue

                    # Call the parser function
                    commands = parser_func(file_path)
                    if commands:  # Only extend if commands were returned
                        commands_to_test.extend(commands)
                except Exception as e:
                    logger.error(f"Error parsing {file_path}: {e}", exc_info=True)

        logger.info(f"Found {len(found_files)} configuration files")
        logger.info(f"Extracted {len(commands_to_test)} commands")

        return commands_to_test

    def _should_process_file(self, file_path: Path) -> bool:
        """Check if file should be processed."""
        try:
            relative_path = str(file_path.relative_to(self.project_path))
        except ValueError:
            return False

        for pattern in self.exclude_patterns:
            if re.search(pattern, relative_path):
                return False

        if self.include_patterns:
            for pattern in self.include_patterns:
                if re.search(pattern, relative_path):
                    return True
            return False

        return True

    # Parser methods (same as before - abbreviated for space)
    def _parse_makefile(self, file_path: Path) -> List[Dict]:
        """Parse Makefile and extract targets as commands.

        Args:
            file_path: Path to the Makefile

        Returns:
            List of command dictionaries with 'command' and 'source' keys
        """
        commands = []

        try:
            with open(file_path, "r", encoding="utf-8") as f:
                content = f.readlines()

            # Skip special targets that don't make sense to run directly
            skip_targets = {
                "PHONY",
                "DEFAULT",
                "SUFFIXES",
                "PRECIOUS",
                "INTERMEDIATE",
                "SECONDARY",
                "SECONDEXPANSION",
                "DELETE_ON_ERROR",
                "IGNORE",
                "LOW_RESOLUTION_TIME",
                "SILENT",
                "EXPORT_ALL_VARIABLES",
                "NOTPARALLEL",
                "ONESHELL",
                "POSIX",
                "DEFAULT_GOAL",
                "help",
            }

            found_targets = set()

            for line in content:
                line = line.strip()
                if not line or line.startswith("#"):
                    continue

                # Skip variable assignments and other non-target lines
                if "=" in line and ":" not in line:
                    continue

                # Handle .PHONY and other special targets
                if line.startswith("."):
                    parts = line.split(":")
                    if len(parts) > 1 and parts[0].strip() == ".PHONY":
                        # Skip adding PHONY targets as commands
                        continue

                # Check if line contains a target (target: [prerequisites])
                if ":" in line:
                    target = line.split(":", 1)[0].strip()

                    # Skip empty targets and special targets
                    if not target or target in skip_targets or target.startswith("."):
                        continue

                    # Skip duplicates
                    if target not in found_targets:
                        found_targets.add(target)
                        commands.append(
                            {
                                "command": f"make {target}",
                                "source": str(file_path.relative_to(self.project_path)),
                                "description": f"Make target: {target}",
                                "type": "make_target",
                            }
                        )

        except Exception as e:
            logger.error(f"Error parsing Makefile {file_path}: {e}")

        return commands

    def _parse_package_json(self, file_path: Path) -> List[Dict]:
        commands = []
        try:
            with open(file_path, "r", encoding="utf-8") as f:
                data = json.load(f)
            scripts = data.get("scripts", {})
            for script_name, script_command in scripts.items():
                commands.append(
                    {
                        "command": f"npm run {script_name}",
                        "description": f"NPM script: {script_name}",
                        "source": str(file_path.relative_to(self.project_path)),
                        "type": "npm_script",
                    }
                )
        except Exception as e:
            logger.error(f"Error parsing {file_path}: {e}")
        return commands

    def _parse_pyproject_toml(self, file_path: Path) -> List[Dict]:
        commands = []
        if not toml:
            return commands
        try:
            with open(file_path, "r", encoding="utf-8") as f:
                data = toml.load(f)
            poetry_scripts = data.get("tool", {}).get("poetry", {}).get("scripts", {})
            for script_name in poetry_scripts:
                commands.append(
                    {
                        "command": f"poetry run {script_name}",
                        "description": f"Poetry script: {script_name}",
                        "source": str(file_path.relative_to(self.project_path)),
                        "type": "poetry_script",
                    }
                )
            if "tool" in data and "pytest" in data["tool"]:
                commands.append(
                    {
                        "command": "python -m pytest",
                        "description": "Run pytest tests",
                        "source": str(file_path.relative_to(self.project_path)),
                        "type": "pytest",
                    }
                )
        except Exception as e:
            logger.error(f"Error parsing {file_path}: {e}")
        return commands

    def _parse_tox_ini(self, file_path: Path) -> List[Dict]:
        commands = []
        try:
            config = configparser.ConfigParser()
            config.read(file_path)
            if "tox" in config:
                envlist = config.get("tox", "envlist", fallback="")
                envs = [env.strip() for env in envlist.split(",") if env.strip()]
                for env in envs:
                    commands.append(
                        {
                            "command": f"tox -e {env}",
                            "description": f"Tox environment: {env}",
                            "source": str(file_path.relative_to(self.project_path)),
                            "type": "tox_env",
                        }
                    )
            commands.append(
                {
                    "command": "tox",
                    "description": "Run all tox environments",
                    "source": str(file_path.relative_to(self.project_path)),
                    "type": "tox",
                }
            )
        except Exception as e:
            logger.error(f"Error parsing {file_path}: {e}")
        return commands

    def _parse_pytest_ini(self, file_path: Path) -> List[Dict]:
        return [
            {
                "command": "python -m pytest",
                "description": "Run pytest tests",
                "source": str(file_path.relative_to(self.project_path)),
                "type": "pytest",
            }
        ]

    def _check_pip_install(self, file_path: Path) -> List[Dict]:
        return [
            {
                "command": f"pip install -r {file_path.name}",
                "description": f"Install pip dependencies from {file_path.name}",
                "source": str(file_path.relative_to(self.project_path)),
                "type": "pip_install",
            }
        ]

    def _parse_setup_py(self, file_path: Path) -> List[Dict]:
        return [
            {
                "command": "python setup.py install",
                "description": "Install Python package",
                "source": str(file_path.relative_to(self.project_path)),
                "type": "setup_install",
            },
            {
                "command": "python setup.py test",
                "description": "Run package tests",
                "source": str(file_path.relative_to(self.project_path)),
                "type": "setup_test",
            },
        ]

    def _parse_dockerfile(self, file_path: Path) -> List[Dict]:
        return [
            {
                "command": f"docker build -t {self.project_path.name.lower()} .",
                "description": "Build Docker image",
                "source": str(file_path.relative_to(self.project_path)),
                "type": "docker_build",
            }
        ]

    def _parse_docker_compose(self, file_path: Path) -> List[Dict]:
        return [
            {
                "command": "docker-compose up --build",
                "description": "Docker Compose up with build",
                "source": str(file_path.relative_to(self.project_path)),
                "type": "docker_compose_up",
            },
            {
                "command": "docker-compose down",
                "description": "Docker Compose down",
                "source": str(file_path.relative_to(self.project_path)),
                "type": "docker_compose_down",
            },
        ]

    def _parse_cmake(self, file_path: Path) -> List[Dict]:
        return [
            {
                "command": "mkdir -p build && cd build && cmake ..",
                "description": "Configure CMake build",
                "source": str(file_path.relative_to(self.project_path)),
                "type": "cmake_configure",
            },
            {
                "command": "cd build && make",
                "description": "Build with CMake",
                "source": str(file_path.relative_to(self.project_path)),
                "type": "cmake_build",
            },
        ]

    def _parse_composer_json(self, file_path: Path) -> List[Dict]:
        commands = []
        try:
            with open(file_path, "r", encoding="utf-8") as f:
                data = json.load(f)
            commands.append(
                {
                    "command": "composer install",
                    "description": "Install Composer dependencies",
                    "source": str(file_path.relative_to(self.project_path)),
                    "type": "composer_install",
                }
            )
            scripts = data.get("scripts", {})
            for script_name in scripts:
                commands.append(
                    {
                        "command": f"composer run-script {script_name}",
                        "description": f"Composer script: {script_name}",
                        "source": str(file_path.relative_to(self.project_path)),
                        "type": "composer_script",
                    }
                )
        except Exception as e:
            logger.error(f"Error parsing {file_path}: {e}")
        return commands

    def _parse_gemfile(self, file_path: Path) -> List[Dict]:
        return [
            {
                "command": "bundle install",
                "description": "Install Ruby gems",
                "source": str(file_path.relative_to(self.project_path)),
                "type": "bundle_install",
            }
        ]

    def _parse_cargo_toml(self, file_path: Path) -> List[Dict]:
        return [
            {
                "command": "cargo build",
                "description": "Build Rust project",
                "source": str(file_path.relative_to(self.project_path)),
                "type": "cargo_build",
            },
            {
                "command": "cargo test",
                "description": "Run Rust tests",
                "source": str(file_path.relative_to(self.project_path)),
                "type": "cargo_test",
            },
            {
                "command": "cargo check",
                "description": "Check Rust code",
                "source": str(file_path.relative_to(self.project_path)),
                "type": "cargo_check",
            },
        ]

    def _check_go_commands(self, file_path: Path) -> List[Dict]:
        return [
            {
                "command": "go build",
                "description": "Build Go project",
                "source": str(file_path.relative_to(self.project_path)),
                "type": "go_build",
            },
            {
                "command": "go test",
                "description": "Run Go tests",
                "source": str(file_path.relative_to(self.project_path)),
                "type": "go_test",
            },
        ]

    def generate_doignore_template(self) -> None:
        """Generate a template .doignore file if it doesn't exist."""
        ignore_file_path = self.project_path / ".doignore"

        if ignore_file_path.exists():
            print(f"📋 .doignore already exists at {ignore_file_path}")
            return

        template_content = """# .doignore - TodoMD Ignore File
# Commands and patterns to skip during testing

# === RECURSIVE/SELF-REFERENTIAL COMMANDS ===
poetry run domd
poetry run project-detector
poetry run cmd-detector
domd

# === INTERACTIVE/BLOCKING COMMANDS ===
npm run dev
npm run start
*serve*
*watch*

# === DEPLOYMENT/DESTRUCTIVE COMMANDS ===
*publish*
*deploy*
*release*

# === SLOW/RESOURCE-INTENSIVE COMMANDS ===
tox
*integration*
*e2e*
*docker*build*

# Add your project-specific ignores below:
"""

        try:
            with open(ignore_file_path, "w", encoding="utf-8") as f:
                f.write(template_content)

            print(f"📝 Created .doignore template at {ignore_file_path}")

        except Exception as e:
            logger.error(f"Error creating .doignore template: {e}")
