"""
Template service for high-level template management operations.

This service extends artifact service to handle PromptTemplate-specific
operations including macro analysis and dependency extraction.
"""

from typing import List, Optional

from markitect.prompts.models import ArtifactMetadata, ArtifactType
from markitect.prompts.templates.models import (
    PromptTemplate,
    TemplateMetadata,
)
from markitect.prompts.templates.analyzer import TemplateAnalyzer, TemplateAnalysisResult
from markitect.prompts.services.artifact_service import ArtifactService
from markitect.prompts.repositories.interfaces import ArtifactNotFoundError


class TemplateService:
    """
    Service for template management operations.

    Provides high-level business logic for creating and analyzing templates,
    building on top of ArtifactService.
    """

    def __init__(self, artifact_service: ArtifactService):
        """
        Initialize service with artifact service.

        Args:
            artifact_service: Artifact service for persistence
        """
        self.artifact_service = artifact_service
        self.analyzer = TemplateAnalyzer()

    def create_template(
        self,
        space_id: str,
        name: str,
        content: str,
        artifact_metadata: Optional[ArtifactMetadata] = None,
        template_metadata: Optional[TemplateMetadata] = None,
        analyze: bool = True,
    ) -> PromptTemplate:
        """
        Create and optionally analyze a new template.

        Args:
            space_id: ID of containing space
            name: Template name
            content: Template content with macros
            artifact_metadata: General artifact metadata
            template_metadata: Template-specific metadata
            analyze: Whether to analyze macros immediately

        Returns:
            Created template (analyzed if analyze=True)

        Raises:
            DuplicateArtifactError: If template already exists
            MacroParsingError: If macro syntax is invalid (when analyze=True)
        """
        # Create template
        template = PromptTemplate.create(
            space_id=space_id,
            name=name,
            content=content,
            artifact_metadata=artifact_metadata,
            template_metadata=template_metadata,
        )

        # Persist artifact
        self.artifact_service.create_artifact(
            space_id=space_id,
            name=name,
            content=content,
            artifact_type=ArtifactType.TEMPLATE,
            metadata=artifact_metadata,
        )

        # Analyze if requested
        if analyze:
            self.analyzer.analyze(template, content)

        return template

    def get_template(self, template_id: str, content: str) -> PromptTemplate:
        """
        Retrieve template by ID.

        Args:
            template_id: Template identifier
            content: Template content (needed to avoid storing content in DB twice)

        Returns:
            PromptTemplate instance

        Raises:
            ArtifactNotFoundError: If template doesn't exist
        """
        artifact = self.artifact_service.get_artifact(template_id)
        if artifact.artifact_type != ArtifactType.TEMPLATE:
            raise ValueError(
                f"Artifact '{template_id}' is not a template "
                f"(type: {artifact.artifact_type})"
            )

        template = PromptTemplate.from_artifact(artifact)
        # Analyze to populate macros
        self.analyzer.analyze(template, content)
        return template

    def get_template_by_name(
        self,
        space_id: str,
        name: str,
        content: str,
    ) -> PromptTemplate:
        """
        Retrieve template by space and name.

        Args:
            space_id: Space identifier
            name: Template name
            content: Template content

        Returns:
            PromptTemplate instance

        Raises:
            ArtifactNotFoundError: If template doesn't exist
        """
        artifact = self.artifact_service.get_artifact_by_name(space_id, name)
        if artifact.artifact_type != ArtifactType.TEMPLATE:
            raise ValueError(
                f"Artifact '{name}' is not a template "
                f"(type: {artifact.artifact_type})"
            )

        template = PromptTemplate.from_artifact(artifact)
        self.analyzer.analyze(template, content)
        return template

    def analyze_template(
        self,
        template: PromptTemplate,
        content: str,
    ) -> TemplateAnalysisResult:
        """
        Analyze template to extract macros and dependencies.

        Args:
            template: Template to analyze
            content: Template content

        Returns:
            Analysis result with dependency information

        Raises:
            MacroParsingError: If macro syntax is invalid
        """
        return self.analyzer.analyze(template, content)

    def list_templates(self, space_id: str) -> List[PromptTemplate]:
        """
        List all templates in a space.

        Note: Templates are returned without macro analysis.
        Call analyze_template() on individual templates as needed.

        Args:
            space_id: Space identifier

        Returns:
            List of templates (unanalyzed)
        """
        artifacts = self.artifact_service.list_artifacts(
            space_id=space_id,
            artifact_type=ArtifactType.TEMPLATE,
        )

        templates = [PromptTemplate.from_artifact(a) for a in artifacts]
        return templates

    def quick_check_content(self, content: str) -> dict:
        """
        Quick validation of template content.

        Useful for checking content before template creation.

        Args:
            content: Template content to check

        Returns:
            Dictionary with macro counts and validation info
        """
        return self.analyzer.quick_check(content)

    def update_template_content(
        self,
        template_id: str,
        new_content: str,
        reanalyze: bool = True,
    ) -> PromptTemplate:
        """
        Update template content.

        Args:
            template_id: Template to update
            new_content: New content
            reanalyze: Whether to reanalyze macros

        Returns:
            Updated template

        Raises:
            ArtifactNotFoundError: If template doesn't exist
            MacroParsingError: If new content has invalid macros
        """
        # Update artifact content
        artifact = self.artifact_service.update_artifact_content(
            template_id,
            new_content,
        )

        # Create template from updated artifact
        template = PromptTemplate.from_artifact(artifact)

        # Reanalyze if requested
        if reanalyze:
            self.analyzer.analyze(template, new_content)

        return template

    def delete_template(self, template_id: str) -> bool:
        """
        Delete a template.

        Args:
            template_id: Template to delete

        Returns:
            True if deleted, False if not found
        """
        return self.artifact_service.delete_artifact(template_id)

    def template_exists(self, space_id: str, name: str) -> bool:
        """
        Check if template exists.

        Args:
            space_id: Space identifier
            name: Template name

        Returns:
            True if template exists
        """
        return self.artifact_service.artifact_exists(space_id, name)
