"""Built-in rule types for core NoteFlow functionality.

Provides ExportRuleType and TriggerRuleType as foundational
rule types that are automatically registered on import.
"""

from __future__ import annotations

from typing import cast

from noteflow.config.constants import (
    ERROR_SUFFIX_MUST_BE_BOOLEAN,
    RULE_FIELD_APP_MATCH_PATTERNS,
    RULE_FIELD_AUTO_START_ENABLED,
    RULE_FIELD_CALENDAR_MATCH_PATTERNS,
    RULE_FIELD_DEFAULT_FORMAT,
    RULE_FIELD_DESCRIPTION,
    RULE_FIELD_INCLUDE_AUDIO,
    RULE_FIELD_INCLUDE_TIMESTAMPS,
    RULE_FIELD_TEMPLATE_ID,
    SCHEMA_TYPE_ARRAY_ITEMS,
    SCHEMA_TYPE_BOOLEAN,
    SCHEMA_TYPE_STRING,
)
from noteflow.domain.rules.registry import RuleContext, RuleResult, RuleType, RuleTypeRegistry

# Valid export formats
VALID_EXPORT_FORMATS = {"markdown", "html", "pdf"}


@RuleTypeRegistry.register
class ExportRuleType(RuleType):
    """Rule type for export configuration.

    Validates and evaluates export-related settings like
    default format, include_audio, include_timestamps, etc.
    """

    name = "export"
    version = 1

    def evaluate(
        self, rule_config: dict[str, object], context: RuleContext
    ) -> RuleResult:
        """Evaluate export rules.

        For simple mode, returns the static configuration.
        Future versions will support conditional evaluation.

        Args:
            rule_config: Export configuration dictionary.
            context: The evaluation context.

        Returns:
            Result with matched=True and config in metadata.
        """
        return RuleResult(matched=True, actions=[], metadata=rule_config)

    def validate_config(self, config: dict[str, object]) -> list[str]:
        """Validate export rule configuration.

        Args:
            config: Configuration to validate.

        Returns:
            List of validation error messages.
        """
        errors: list[str] = []

        if RULE_FIELD_DEFAULT_FORMAT in config:
            fmt = config[RULE_FIELD_DEFAULT_FORMAT]
            if fmt not in VALID_EXPORT_FORMATS:
                errors.append(
                    f"Invalid format: {fmt}. Must be one of: {VALID_EXPORT_FORMATS}"
                )

        if RULE_FIELD_INCLUDE_AUDIO in config and not isinstance(config[RULE_FIELD_INCLUDE_AUDIO], bool):
            errors.append(f"{RULE_FIELD_INCLUDE_AUDIO}{ERROR_SUFFIX_MUST_BE_BOOLEAN}")

        if RULE_FIELD_INCLUDE_TIMESTAMPS in config and not isinstance(config[RULE_FIELD_INCLUDE_TIMESTAMPS], bool):
            errors.append(f"{RULE_FIELD_INCLUDE_TIMESTAMPS}{ERROR_SUFFIX_MUST_BE_BOOLEAN}")

        return errors

    def get_schema(self) -> dict[str, object]:
        """Return JSON schema for export configuration.

        Returns:
            JSON Schema dictionary.
        """
        return {
            "type": "object",
            "properties": {
                RULE_FIELD_DEFAULT_FORMAT: {
                    "type": SCHEMA_TYPE_STRING,
                    "enum": list(VALID_EXPORT_FORMATS),
                    RULE_FIELD_DESCRIPTION: "Default export format",
                },
                RULE_FIELD_INCLUDE_AUDIO: {
                    "type": SCHEMA_TYPE_BOOLEAN,
                    RULE_FIELD_DESCRIPTION: "Include audio file in export",
                },
                RULE_FIELD_INCLUDE_TIMESTAMPS: {
                    "type": SCHEMA_TYPE_BOOLEAN,
                    RULE_FIELD_DESCRIPTION: "Include timestamps in transcript",
                },
                RULE_FIELD_TEMPLATE_ID: {
                    "type": SCHEMA_TYPE_STRING,
                    "format": "uuid",
                    RULE_FIELD_DESCRIPTION: "Export template ID",
                },
            },
        }


@RuleTypeRegistry.register
class TriggerRuleType(RuleType):
    """Rule type for auto-start triggers.

    Validates and evaluates trigger-related settings like
    auto_start_enabled, calendar patterns, app patterns, etc.
    """

    name = "trigger"
    version = 1

    def evaluate(
        self, rule_config: dict[str, object], context: RuleContext
    ) -> RuleResult:
        """Evaluate trigger rules.

        For simple mode, returns the static configuration.
        Future versions will support calendar event matching
        and app detection conditions.

        Args:
            rule_config: Trigger configuration dictionary.
            context: The evaluation context.

        Returns:
            Result with matched status and config in metadata.
        """
        # Simple mode: just return config
        # Future: evaluate against calendar_event, app_name, etc.
        return RuleResult(matched=True, actions=[], metadata=rule_config)

    def validate_config(self, config: dict[str, object]) -> list[str]:
        """Validate trigger rule configuration.

        Args:
            config: Configuration to validate.

        Returns:
            List of validation error messages.
        """
        errors: list[str] = []

        if RULE_FIELD_AUTO_START_ENABLED in config and not isinstance(
            config[RULE_FIELD_AUTO_START_ENABLED], bool
        ):
            errors.append(f"{RULE_FIELD_AUTO_START_ENABLED}{ERROR_SUFFIX_MUST_BE_BOOLEAN}")

        if RULE_FIELD_CALENDAR_MATCH_PATTERNS in config:
            patterns = config[RULE_FIELD_CALENDAR_MATCH_PATTERNS]
            if not isinstance(patterns, list):
                errors.append(f"{RULE_FIELD_CALENDAR_MATCH_PATTERNS} must be a list")
            else:
                calendar_patterns = cast(list[object], patterns)
                if not all(isinstance(pattern, str) for pattern in calendar_patterns):
                    errors.append(
                        f"{RULE_FIELD_CALENDAR_MATCH_PATTERNS} must contain only strings"
                    )

        if RULE_FIELD_APP_MATCH_PATTERNS in config:
            patterns = config[RULE_FIELD_APP_MATCH_PATTERNS]
            if not isinstance(patterns, list):
                errors.append(f"{RULE_FIELD_APP_MATCH_PATTERNS} must be a list")
            else:
                app_patterns = cast(list[object], patterns)
                if not all(isinstance(pattern, str) for pattern in app_patterns):
                    errors.append("app_match_patterns must contain only strings")

        return errors

    def get_schema(self) -> dict[str, object]:
        """Return JSON schema for trigger configuration.

        Returns:
            JSON Schema dictionary.
        """
        return {
            "type": "object",
            "properties": {
                RULE_FIELD_AUTO_START_ENABLED: {
                    "type": SCHEMA_TYPE_BOOLEAN,
                    RULE_FIELD_DESCRIPTION: "Enable automatic recording start",
                },
                RULE_FIELD_CALENDAR_MATCH_PATTERNS: {
                    "type": "array",
                    SCHEMA_TYPE_ARRAY_ITEMS: {"type": SCHEMA_TYPE_STRING},
                    RULE_FIELD_DESCRIPTION: "Glob patterns for calendar event titles",
                },
                RULE_FIELD_APP_MATCH_PATTERNS: {
                    "type": "array",
                    SCHEMA_TYPE_ARRAY_ITEMS: {"type": SCHEMA_TYPE_STRING},
                    RULE_FIELD_DESCRIPTION: "Glob patterns for application names",
                },
            },
        }
