"""
Manifest parser and writer for CARL Control Panel.
Handles reading and modifying .carl/manifest file.
"""
from pathlib import Path
import re


class ManifestManager:
    """Manages reading and writing to CARL manifest files."""

    # Core toggles we manage in MVP
    CORE_TOGGLES = [
        'DEVMODE',
        'GLOBAL_STATE'
    ]

    def __init__(self, carl_path: Path):
        """Initialize with path to .carl directory."""
        self.carl_path = Path(carl_path)
        self.manifest_path = self.carl_path / 'manifest'

    def exists(self) -> bool:
        """Check if manifest file exists."""
        return self.manifest_path.exists()

    def read_toggles(self) -> dict:
        """Read all toggle values from manifest.

        Returns:
            Dict with toggle names as keys, boolean values.
            Includes core toggles and all domain _STATE values.
            Missing toggles default to False.
        """
        toggles = {t: False for t in self.CORE_TOGGLES}

        if not self.exists():
            return toggles

        content = self.manifest_path.read_text()

        for line in content.splitlines():
            line = line.strip()

            # Skip comments and empty lines
            if not line or line.startswith('#'):
                continue

            # Parse KEY=value
            if '=' in line:
                key, value = line.split('=', 1)
                key = key.strip()
                value = value.strip().lower()

                # Handle core toggles
                if key in toggles:
                    if key in ['GLOBAL_STATE']:
                        toggles[key] = value == 'active'
                    else:
                        toggles[key] = value in ['true', '1', 'yes', 'on', 'active']
                # Also capture domain _STATE values (e.g., DEVELOPMENT_STATE, COMMANDS_STATE)
                elif key.endswith('_STATE'):
                    toggles[key] = value in ['active', 'true', '1', 'yes', 'on']

        return toggles

    def write_toggle(self, key: str, value: bool) -> bool:
        """Update a single toggle value in manifest.

        Args:
            key: Toggle name (e.g., 'DEVMODE')
            value: New boolean value

        Returns:
            True if successful, False otherwise.
        """
        if not self.exists():
            return False

        content = self.manifest_path.read_text()
        lines = content.splitlines()

        # Determine the string value to write
        if key == 'GLOBAL_STATE':
            str_value = 'active' if value else 'inactive'
        else:
            str_value = 'true' if value else 'false'

        # Find and update the line
        found = False
        for i, line in enumerate(lines):
            stripped = line.strip()
            if stripped.startswith(f'{key}='):
                # Preserve any inline comments
                comment = ''
                if '#' in line:
                    parts = line.split('#', 1)
                    comment = ' #' + parts[1]

                lines[i] = f'{key}={str_value}{comment}'
                found = True
                break

        if not found:
            # Key doesn't exist - add it at the end
            lines.append(f'{key}={str_value}')

        self.manifest_path.write_text('\n'.join(lines))
        return True

    def set_value(self, key: str, value: str) -> bool:
        """Set an arbitrary key-value pair in manifest.

        Args:
            key: Key name (e.g., 'GIT_RECALL')
            value: String value to set

        Returns:
            True if successful, False otherwise.
        """
        if not self.exists():
            return False

        content = self.manifest_path.read_text()
        lines = content.splitlines()

        # Find and update the line
        found = False
        for i, line in enumerate(lines):
            stripped = line.strip()
            if stripped.startswith(f'{key}='):
                lines[i] = f'{key}={value}'
                found = True
                break

        if not found:
            # Key doesn't exist - add it at the end
            lines.append(f'{key}={value}')

        self.manifest_path.write_text('\n'.join(lines))
        return True

    def get_value(self, key: str) -> str:
        """Get the value for a key from manifest.

        Args:
            key: Key name (e.g., 'GIT_RECALL')

        Returns:
            String value if found, empty string otherwise.
        """
        if not self.exists():
            return ''

        content = self.manifest_path.read_text()
        for line in content.splitlines():
            stripped = line.strip()
            if stripped.startswith(f'{key}='):
                return stripped.split('=', 1)[1]
        return ''

    def write_toggles(self, toggles: dict) -> bool:
        """Update multiple toggle values at once.

        Args:
            toggles: Dict of {toggle_name: bool_value}

        Returns:
            True if all successful.
        """
        success = True
        for key, value in toggles.items():
            if key in self.CORE_TOGGLES:
                if not self.write_toggle(key, value):
                    success = False
        return success

    def get_carl_info(self) -> dict:
        """Get basic info about the CARL installation.

        Returns:
            Dict with path info and validation status.
        """
        return {
            'carl_path': str(self.carl_path),
            'manifest_exists': self.exists(),
            'manifest_path': str(self.manifest_path),
            'is_valid': self.exists() and self.carl_path.is_dir()
        }
