"""Configuration service for Portal."""

from __future__ import annotations

from pathlib import Path
from typing import TYPE_CHECKING, Any

if TYPE_CHECKING:
    from portal.core.domain.models.config import PortalConfig
    from portal.core.domain.models.template import WorktreeTemplate
    from portal.infrastructure.config import YamlConfigRepository


class ConfigService:
    """Service for managing configuration."""

    def __init__(self, config_repository: YamlConfigRepository):
        self.config_repository = config_repository
        self._config: PortalConfig | None = None

    async def get_config(self, project_path: Path | None = None) -> PortalConfig:
        """Get merged configuration."""
        if self._config is None or project_path:
            self._config = await self.config_repository.load_config(project_path)
        return self._config

    async def get_global_config(self) -> PortalConfig:
        """Get global configuration only."""
        config = await self.config_repository.load_config()
        return config

    async def get_local_config_path(self) -> Path:
        """Get path to local configuration file."""
        return Path.cwd() / ".portal" / "config.yaml"

    async def get_global_config_path(self) -> Path:
        """Get path to global configuration file."""
        return Path.home() / ".portal" / "config.yaml"

    async def set_config_value(self, key_parts: list[str], value: str) -> dict[str, Any]:
        """Set a configuration value using key path."""
        result: dict[str, Any] = {"success": True, "errors": [], "warnings": []}

        try:
            config = await self.get_config()
            config_dict = config.model_dump()

            # Navigate to the target location
            target = config_dict
            for part in key_parts[:-1]:
                target = target.setdefault(part, {})
            target[key_parts[-1]] = value

            # Validate and save locally
            from portal.core.domain.models.config import PortalConfig

            updated_config = PortalConfig.model_validate(config_dict)
            await self.config_repository.save_project_config(
                Path.cwd(), updated_config.model_dump()
            )
            self._config = updated_config

        except Exception as e:
            result["success"] = False
            result["errors"].append(str(e))

        return result

    async def set_global_config_value(self, key_parts: list[str], value: str) -> dict[str, Any]:
        """Set a global configuration value using key path."""
        result: dict[str, Any] = {"success": True, "errors": [], "warnings": []}

        try:
            config = await self.get_global_config()
            config_dict = config.model_dump()

            # Navigate to the target location
            target = config_dict
            for part in key_parts[:-1]:
                target = target.setdefault(part, {})
            target[key_parts[-1]] = value

            # Validate and save globally
            from portal.core.domain.models.config import PortalConfig

            updated_config = PortalConfig.model_validate(config_dict)
            await self.config_repository.save_global_config(updated_config)

        except Exception as e:
            result["success"] = False
            result["errors"].append(str(e))

        return result

    async def reset_local_config(self) -> None:
        """Reset local configuration to defaults."""
        from portal.core.domain.models.config import PortalConfig

        default_config = PortalConfig(
            version="1.0", base_dir="../{project}_worktrees", default_base_branch="main"
        )
        await self.config_repository.save_project_config(Path.cwd(), default_config.model_dump())
        self._config = default_config

    async def reset_global_config(self) -> None:
        """Reset global configuration to defaults."""
        from portal.core.domain.models.config import PortalConfig

        default_config = PortalConfig(
            version="1.0", base_dir="../{project}_worktrees", default_base_branch="main"
        )
        await self.config_repository.save_global_config(default_config)

    async def validate_config(self) -> dict[str, Any]:
        """Validate current configuration."""
        result: dict[str, Any] = {"success": True, "errors": [], "warnings": []}

        try:
            config = await self.get_config()

            # Basic validation - check required fields exist
            if not config.base_dir:
                result["errors"].append("base_dir is required")

            if not config.version:
                result["errors"].append("version is required")

            # Check if base_dir is valid
            import os

            expanded_base = os.path.expanduser(config.base_dir)
            base_path = Path(expanded_base.replace("{project}", "test"))
            if not base_path.parent.exists():
                result["warnings"].append(
                    f"Base directory parent does not exist: {base_path.parent}"
                )

            result["success"] = len(result["errors"]) == 0

        except Exception as e:
            result["success"] = False
            result["errors"].append(str(e))

        return result

    async def update_global_config(self, updates: dict[str, Any]) -> PortalConfig:
        """Update global configuration."""
        from portal.core.domain.models.config import PortalConfig

        # Load current config
        config = await self.config_repository.load_config()

        # Apply updates
        config_dict = config.model_dump()
        for key, value in updates.items():
            if "." in key:
                # Handle nested keys like 'colors.enabled'
                parts = key.split(".")
                target = config_dict
                for part in parts[:-1]:
                    target = target.setdefault(part, {})
                target[parts[-1]] = value
            else:
                config_dict[key] = value

        # Validate and save
        updated_config = PortalConfig.model_validate(config_dict)
        await self.config_repository.save_global_config(updated_config)

        self._config = updated_config
        return updated_config

    async def get_template(self, template_name: str) -> WorktreeTemplate | None:
        """Get a worktree template by name."""
        template = await self.config_repository.load_template(template_name)
        return template

    async def list_templates(self) -> list[str]:
        """List available template names."""
        templates = await self.config_repository.list_templates()
        return templates

    def get_worktree_base_dir(self, project_name: str) -> Path:
        """Get the base directory for worktrees."""
        from portal.core.domain.models.config import PortalConfig

        config = self._config or PortalConfig(
            version="1.0", base_dir="../{project}_worktrees", default_base_branch="main"
        )
        base_dir = config.base_dir.replace("{project}", project_name)
        return Path(base_dir)

    def get_editor_command(self, worktree_path: Path) -> str:
        """Get the command to open editor for a worktree."""
        from portal.core.domain.models.config import PortalConfig

        config = self._config or PortalConfig(
            version="1.0", base_dir="../{project}_worktrees", default_base_branch="main"
        )
        editor = config.editor.default

        # Build command based on editor
        if editor == "cursor":
            return f'cursor "{worktree_path}"'
        elif editor == "code" or editor == "vscode":
            return f'code "{worktree_path}"'
        elif editor == "vim" or editor == "nvim":
            return f'{editor} "+cd {worktree_path}"'
        else:
            # Generic editor command
            return f'{editor} "{worktree_path}"'
