"""Constitution assembly and management."""

import re

from dd_dm.core.config import ConfigManager
from dd_dm.core.module_manager import ModuleManager
from dd_dm.models.config import Config


class ConstitutionManager:
    """Manages constitution file assembly and updates."""

    MODULE_START_MARKER = "<!-- dd-dm:modules:start -->"
    MODULE_END_MARKER = "<!-- dd-dm:modules:end -->"
    MODULE_SECTION_TEMPLATE = """
<!-- dd-dm:module:{name}:start -->
{content}
<!-- dd-dm:module:{name}:end -->
"""

    def __init__(
        self,
        config_manager: ConfigManager,
        module_manager: ModuleManager,
    ) -> None:
        """Initialize constitution manager.

        Args:
            config_manager: Configuration manager instance.
            module_manager: Module manager instance.
        """
        self.config_manager = config_manager
        self.module_manager = module_manager
        self.constitution_path = config_manager.project_root / "CONSTITUTION.md"

    def assemble(self, config: Config) -> str:
        """Assemble the constitution from enabled modules.

        Args:
            config: Current configuration.

        Returns:
            Assembled constitution content.
        """
        # Load the base template
        template_path = self.config_manager.cache_dir / "CONSTITUTION.md"
        if template_path.exists():
            template = template_path.read_text()
        else:
            template = self._default_template()

        # Build module content
        module_content = self._build_module_content(config)

        # Insert modules into template
        assembled = self._insert_modules(template, module_content)

        return assembled

    def write(self, config: Config) -> None:
        """Assemble and write the constitution file.

        Args:
            config: Current configuration.
        """
        content = self.assemble(config)
        self.constitution_path.write_text(content)

    def read_current(self) -> str | None:
        """Read the current constitution file.

        Returns:
            Current constitution content or None if not exists.
        """
        if self.constitution_path.exists():
            return self.constitution_path.read_text()
        return None

    def get_enabled_modules_from_file(self) -> list[str]:
        """Extract enabled module names from current constitution.

        Returns:
            List of module names found in the constitution.
        """
        content = self.read_current()
        if not content:
            return []

        # Find all module sections
        pattern = r"<!-- dd-dm:module:([^:]+):start -->"
        matches = re.findall(pattern, content)
        return matches

    def _build_module_content(self, config: Config) -> str:
        """Build the content for all enabled modules.

        Args:
            config: Current configuration.

        Returns:
            Combined module content.
        """
        parts: list[str] = []

        for module_name in config.modules.enabled:
            try:
                module = self.module_manager.get_module(module_name)
                section = self.MODULE_SECTION_TEMPLATE.format(
                    name=module_name,
                    content=module.content.strip(),
                )
                parts.append(section)
            except Exception:
                # Skip modules that can't be loaded
                continue

        return "\n".join(parts)

    def _insert_modules(self, template: str, module_content: str) -> str:
        """Insert module content into the template.

        Args:
            template: Base template with markers.
            module_content: Content to insert.

        Returns:
            Template with modules inserted.
        """
        # Pattern to match the modules section
        pattern = re.compile(
            rf"({re.escape(self.MODULE_START_MARKER)})"
            r".*?"
            rf"({re.escape(self.MODULE_END_MARKER)})",
            re.DOTALL,
        )

        replacement = (
            f"{self.MODULE_START_MARKER}\n{module_content}\n{self.MODULE_END_MARKER}"
        )

        if pattern.search(template):
            return pattern.sub(replacement, template)
        else:
            # If no markers found, append at the end
            return template + "\n\n" + replacement

    def _default_template(self) -> str:
        """Return the default constitution template.

        Returns:
            Default template content.
        """
        return f"""# Project Constitution

<!-- dd-dm: DO NOT EDIT THIS FILE DIRECTLY -->
<!-- Use `dd-dm add/delete/create` commands to manage modules -->
<!-- This file is auto-generated from enabled modules -->

## Overview

This document defines the engineering standards and conventions for this project.

---

{self.MODULE_START_MARKER}
<!-- Modules will be inserted here automatically by dd-dm -->
{self.MODULE_END_MARKER}

---

## Additional Notes

- This constitution is managed by dd-dm
- To add modules: `dd-dm add <module-name>`
- To remove modules: `dd-dm delete <module-name>`
- To create custom modules: `dd-dm create <module-name>`
"""

    def copy_template_files(self) -> None:
        """Copy template files from cache to project root."""
        cache_dir = self.config_manager.cache_dir

        # Copy CONSTITUTION.md
        src_constitution = cache_dir / "CONSTITUTION.md"
        if src_constitution.exists():
            self.constitution_path.write_text(src_constitution.read_text())

        # Copy CLAUDE.md
        src_claude = cache_dir / "CLAUDE.md"
        dst_claude = self.config_manager.project_root / "CLAUDE.md"
        if src_claude.exists():
            dst_claude.write_text(src_claude.read_text())

        # Copy AGENTS.md
        src_agents = cache_dir / "AGENTS.md"
        dst_agents = self.config_manager.project_root / "AGENTS.md"
        if src_agents.exists():
            dst_agents.write_text(src_agents.read_text())
