"""SubAgent synchronization logic."""

import json
import os
import re
import shutil
import tempfile
from pathlib import Path
from typing import Any, Dict, List, Optional

import yaml

from .base_sync import BaseSync
from .version_utils import normalize_support_field, validate_metadata, validate_support_agents


class SubAgentSync(BaseSync):
    """Handles SubAgent synchronization operations."""

    def __init__(
        self,
        base_dir: str,
        target_agents: List[str],
        current_versions: Dict[str, str],
        debug_mode: bool = False,
        tracker: Optional[Any] = None,
        parent_config_path: Optional[str] = None,
    ):
        """
        Initialize SubAgentSync.

        Args:
            base_dir: Base directory for operations
            target_agents: List of target agents
            current_versions: Dictionary mapping agent names to current versions
            debug_mode: Enable debug logging
            tracker: PackageTracker instance
            parent_config_path: Path to parent config file
        """
        super().__init__(
            base_dir, target_agents, current_versions, debug_mode, tracker, parent_config_path
        )
        self.vibe_agents_dir = self.vibe_package_dir / "agents"
        self.vibe_agents_dir.mkdir(parents=True, exist_ok=True)
        self._debug_log(f"Created agents directory: {self.vibe_agents_dir}")

    def sync_subagent(self, subagent_name: str, subagent_config: Dict[str, Any]) -> List[str]:
        """
        Synchronize a SubAgent from git repository.

        Args:
            subagent_name: Name of the SubAgent
            subagent_config: SubAgent configuration dictionary

        Returns:
            List of warning messages
        """
        warnings = []

        git_url = subagent_config["git"]
        git_tag = subagent_config["git_tag"]

        self._debug_log(
            f"Syncing SubAgent '{subagent_name}' from {git_url} (tag/branch: {git_tag})"
        )

        temp_dir = self.vibe_agents_dir / subagent_name
        self._debug_log(f"Temporary directory: {temp_dir}")

        try:
            # Clone the repository
            self._debug_log("Cloning repository...")
            self._clone_repository(git_url, git_tag, temp_dir)
            self._debug_log("Repository cloned successfully")

            # Handle subdirectory path if specified
            subagent_path = subagent_config.get("path")
            if subagent_path:
                self._debug_log(f"Using subdirectory path: {subagent_path}")
                temp_dir = temp_dir / subagent_path
                if not temp_dir.exists():
                    raise FileNotFoundError(
                        f"Path '{subagent_path}' not found in repository '{git_url}'"
                    )
                self._debug_log(f"Working in subdirectory: {temp_dir}")

            # Remove .git directory
            git_dir = temp_dir / ".git"
            if git_dir.exists():
                self._debug_log("Removing .git directory...")
                self._remove_git_directory(git_dir)
                self._debug_log(".git directory removed")

            # Find markdown files in root directory only
            self._debug_log("Searching for markdown files in root directory...")
            md_files = list(temp_dir.glob("*.md"))
            self._debug_log(f"Found {len(md_files)} markdown file(s): {[f.name for f in md_files]}")

            if not md_files:
                self._debug_log("No markdown files found!")
                raise FileNotFoundError(f"No markdown file found in {subagent_name}")

            # Read and validate metadata from first md file
            subagent_md_path = md_files[0]
            self._debug_log(f"Using first markdown file: {subagent_md_path.name}")

            meta_data = self._read_subagent_metadata(subagent_md_path)
            self._debug_log(f"Raw metadata: {meta_data}")
            meta_data = normalize_support_field(meta_data)
            self._debug_log(f"Normalized metadata: {meta_data}")

            metadata_warnings = validate_metadata(meta_data, f"SubAgent '{subagent_name}'")
            warnings.extend(metadata_warnings)

            # Validate support_agents
            self._debug_log("Validating support_agents...")
            support_agents = meta_data.get("support_agents", {})
            version_warnings = validate_support_agents(
                support_agents,
                self.target_agents,
                self.current_versions,
                f"SubAgent '{subagent_name}'",
            )
            warnings.extend(version_warnings)
            self._debug_log(f"Support_agents validation complete, {len(version_warnings)} warnings")

            # Copy to target directories
            self._debug_log(f"Copying to target agents: {self.target_agents}")
            for agent in self.target_agents:
                target_agents_dir = self.base_dir / f".{agent}" / "agents"
                target_agents_dir.mkdir(parents=True, exist_ok=True)

                self._debug_log(f"Copying {len(md_files)} md file(s) to: {target_agents_dir}")
                for md_file in md_files:
                    target_file = target_agents_dir / md_file.name
                    self._debug_log(f"  Copying: {md_file.name}")
                    shutil.copy2(md_file, target_file)

                print(
                    f"[OK] Synced SubAgent '{subagent_name}' ({len(md_files)} file(s)) to .{agent}/agents/"
                )
                self._debug_log(f"Successfully copied to .{agent}/agents/")

            # Check for vibe_package.json and sync dependencies
            vibe_package_json = temp_dir / "vibe_package.json"
            self._debug_log(f"Checking for vibe_package.json: {vibe_package_json.exists()}")

            if vibe_package_json.exists() and self.tracker:
                self._debug_log(f"Found vibe_package.json in SubAgent '{subagent_name}'")
                print(f"\nFound vibe_package.json in SubAgent '{subagent_name}'")
                self._sync_subagent_dependencies(vibe_package_json, subagent_name)

        except Exception:
            # Clean up on error
            if temp_dir.exists():
                self._debug_log("Cleaning up temporary directory...")
                shutil.rmtree(temp_dir, ignore_errors=True)
            raise

        # Clean up temp directory
        self._debug_log("Cleaning up temporary directory...")
        if temp_dir.exists():
            shutil.rmtree(temp_dir, ignore_errors=True)
        self._debug_log("Cleanup complete")

        return warnings

    def _read_subagent_metadata(self, subagent_md_path: Path) -> Dict[str, Any]:
        """
        Read metadata from SubAgent markdown file.

        Args:
            subagent_md_path: Path to SubAgent markdown file

        Returns:
            Dictionary containing metadata
        """
        with open(subagent_md_path, "r", encoding="utf-8") as f:
            content = f.read()

        match = re.match(r"^---\s*\n(.*?)\n---\s*\n", content, re.DOTALL)
        if not match:
            return {}

        yaml_content = match.group(1)
        return yaml.safe_load(yaml_content)

    def _sync_subagent_dependencies(self, config_path: Path, subagent_name: str) -> None:
        """
        Sync dependencies from a SubAgent's vibe_package.json.

        Args:
            config_path: Path to vibe_package.json
            subagent_name: Name of the SubAgent (for logging)
        """
        self._debug_log(f"Syncing dependencies from {subagent_name}'s vibe_package.json")

        # Check for circular dependencies
        if self.tracker.check_circular(config_path):
            self._debug_log(f"Warning: Circular dependency detected, skipping {config_path}")
            print(f"Warning: Circular dependency detected, skipping {config_path}")
            return

        # Check if already loaded
        if self.tracker.is_config_loaded(config_path):
            self._debug_log(f"Config already loaded, skipping: {config_path}")
            return

        # Mark as loaded and push to stack
        self.tracker.mark_config_loaded(config_path)
        self.tracker.push_config(config_path)

        temp_config_path: Optional[str] = None

        try:
            from .config_parser import VibePackageConfig

            # Read the config file
            with open(config_path, "r", encoding="utf-8") as f:
                config_data = json.load(f)

            # Check if target_agents field needs to use parent's target_agents
            original_target_agents = config_data.get("target_agents", [])
            should_use_parent_target_agents = (
                not original_target_agents
                or original_target_agents == ["parent"]
                or (isinstance(original_target_agents, str) and original_target_agents == "parent")
            )

            if should_use_parent_target_agents:
                self._debug_log(f"Using parent's target_agents: {self.target_agents}")
                config_data["target_agents"] = self.target_agents

                # Create a temporary config file
                with tempfile.NamedTemporaryFile(
                    mode="w", suffix=".json", delete=False, encoding="utf-8"
                ) as temp_file:
                    json.dump(config_data, temp_file, indent=2, ensure_ascii=False)
                    temp_config_path = temp_file.name

                config = VibePackageConfig(temp_config_path)
            else:
                config = VibePackageConfig(str(config_path))

            target_agents = self.target_agents

            print(f"\n{'=' * 60}")
            print(f"Syncing dependencies from SubAgent: {subagent_name}")
            print(f"{'=' * 60}")

            # Sync SKILLs
            skills = config.get_skills()
            if skills:
                print(f"\nFound {len(skills)} SKILL(s) in SubAgent dependencies")
                from .skill_sync import SkillSync

                skill_sync = SkillSync(
                    str(self.base_dir),
                    target_agents,
                    self.current_versions,
                    self.debug_mode,
                    self.tracker,
                    str(config_path),
                )

                for skill_name, skill_config in skills.items():
                    if self.tracker.is_skill_loaded(skill_name):
                        self._debug_log(f"SKILL '{skill_name}' already loaded, skipping")
                        continue

                    try:
                        print(f"\nProcessing SKILL: {skill_name}")
                        skill_sync.sync_skill(skill_name, skill_config)
                        self.tracker.mark_skill_loaded(skill_name)
                    except Exception as e:
                        self._debug_log(f"Error syncing SKILL '{skill_name}': {e}")
                        print(f"Error syncing SKILL '{skill_name}': {e}")

            # Sync SubAgents (recursive)
            subagents = config.get_subagents()
            if subagents:
                print(f"\nFound {len(subagents)} SubAgent(s) in SubAgent dependencies")

                for subagent_dep_name, subagent_dep_config in subagents.items():
                    if self.tracker.is_subagent_loaded(subagent_dep_name):
                        self._debug_log(f"SubAgent '{subagent_dep_name}' already loaded, skipping")
                        continue

                    try:
                        print(f"\nProcessing SubAgent: {subagent_dep_name}")
                        self.sync_subagent(subagent_dep_name, subagent_dep_config)
                        self.tracker.mark_subagent_loaded(subagent_dep_name)
                    except Exception as e:
                        self._debug_log(f"Error syncing SubAgent '{subagent_dep_name}': {e}")
                        print(f"Error syncing SubAgent '{subagent_dep_name}': {e}")

            # Install MCPs
            mcps = config.get_mcps()
            if mcps:
                print(f"\nFound {len(mcps)} MCP(s) in SubAgent dependencies")
                from .mcp_installer import MCPInstaller

                mcp_installer = MCPInstaller(
                    str(self.base_dir), target_agents, self.debug_mode, self.tracker
                )

                for mcp_name, mcp_config in mcps.items():
                    if self.tracker.is_mcp_loaded(mcp_name):
                        self._debug_log(f"MCP '{mcp_name}' already installed, skipping")
                        continue

                    try:
                        print(f"\nProcessing MCP: {mcp_name}")
                        mcp_installer.install_mcp(mcp_name, mcp_config)
                        self.tracker.mark_mcp_loaded(mcp_name)
                    except Exception as e:
                        self._debug_log(f"Error installing MCP '{mcp_name}': {e}")
                        print(f"Error installing MCP '{mcp_name}': {e}")

            print(f"\n{'=' * 60}")
            print(f"Finished syncing dependencies from SubAgent: {subagent_name}")
            print(f"{'=' * 60}")

        except Exception as e:
            self._debug_log(f"Error syncing dependencies from {subagent_name}: {e}")
            print(f"Error syncing dependencies from {subagent_name}: {e}")
        finally:
            self.tracker.pop_config()

            if temp_config_path and os.path.exists(temp_config_path):
                try:
                    os.unlink(temp_config_path)
                    self._debug_log(f"Cleaned up temporary config file: {temp_config_path}")
                except Exception as e:
                    self._debug_log(f"Failed to clean up temporary config file: {e}")
