"""Snowflake Task compiler — NEW capability filling a gap.

Generates CREATE TASK statements for scheduled execution of
SDK workflows in Snowflake.
"""

from __future__ import annotations

import logging
from typing import Any, Dict, List, Optional

from databridge_core.sdk.compiler.base import BaseCompiler
from databridge_core.sdk.core.exceptions import CompilationError
from databridge_core.sdk.core.types import CompiledArtifact

logger = logging.getLogger(__name__)


class TaskCompiler(BaseCompiler):
    """Compile SDK workflows into Snowflake Tasks.

    Generates CREATE TASK DDL with:
        - SCHEDULE (cron or interval) for root tasks
        - AFTER dependencies for child tasks (mutually exclusive with SCHEDULE)
        - WAREHOUSE assignment
        - WHEN conditions
        - Error notification integration
    """

    object_type = "TASK"

    def compile(
        self,
        workflow_name: str,
        params: Dict[str, Any],
        target_database: Optional[str] = None,
        target_schema: Optional[str] = None,
    ) -> List[CompiledArtifact]:
        """Compile into Snowflake Task DDL.

        Required params:
            task_name: Name of the task.
            warehouse: Warehouse to use.
            sql_statement: SQL to execute (or stored proc call).
            schedule OR after: Root tasks need schedule; child tasks need after.

        Optional params:
            when: WHEN condition expression.
            error_integration: Notification integration name.
            suspend_after_num_failures: Auto-suspend threshold (int).
            allow_overlapping_execution: Allow overlap (bool, default False).
            comment: DDL comment.
        """
        task_name = params.get("task_name")
        warehouse = params.get("warehouse")
        sql_statement = params.get("sql_statement")
        schedule = params.get("schedule")
        after = params.get("after")  # list of predecessor task names

        if not task_name:
            raise CompilationError("TaskCompiler requires 'task_name' param")
        if not warehouse:
            raise CompilationError("TaskCompiler requires 'warehouse' param")
        if not sql_statement:
            raise CompilationError("TaskCompiler requires 'sql_statement' param")
        if schedule and after:
            raise CompilationError(
                "TaskCompiler: 'schedule' and 'after' are mutually exclusive — "
                "root tasks use SCHEDULE, child tasks use AFTER"
            )
        if not schedule and not after:
            raise CompilationError(
                "TaskCompiler requires either 'schedule' (root task) "
                "or 'after' (child task)"
            )

        when = params.get("when")
        error_integration = params.get("error_integration")
        suspend_after = params.get("suspend_after_num_failures")
        allow_overlap = params.get("allow_overlapping_execution", False)
        comment = params.get("comment")

        fqn = self._fqn(task_name, target_database, target_schema)

        # Build DDL
        ddl_parts = [self._header(fqn)]
        ddl_parts.append(f"CREATE OR REPLACE TASK {fqn}")
        ddl_parts.append(f"  WAREHOUSE = {warehouse}")

        if schedule:
            ddl_parts.append(f"  SCHEDULE = '{schedule}'")

        if after:
            after_list = after if isinstance(after, list) else [after]
            after_fqns = [
                self._fqn(t, target_database, target_schema) for t in after_list
            ]
            ddl_parts.append(f"  AFTER {', '.join(after_fqns)}")

        if error_integration:
            ddl_parts.append(f"  ERROR_INTEGRATION = {error_integration}")

        if suspend_after is not None:
            ddl_parts.append(f"  SUSPEND_TASK_AFTER_NUM_FAILURES = {suspend_after}")

        if allow_overlap:
            ddl_parts.append("  ALLOW_OVERLAPPING_EXECUTION = TRUE")

        if comment:
            ddl_parts.append(f"  COMMENT = '{comment}'")

        if when:
            ddl_parts.append(f"WHEN\n  {when}")

        ddl_parts.append(f"AS\n  {sql_statement};")

        ddl = "\n".join(ddl_parts)

        # Dependencies: predecessor tasks
        dependencies: List[str] = []
        if after:
            after_list = after if isinstance(after, list) else [after]
            dependencies = [
                self._fqn(t, target_database, target_schema) for t in after_list
            ]

        artifact = CompiledArtifact(
            artifact_type="task",
            object_name=fqn,
            ddl=ddl,
            dependencies=dependencies,
            source_workflow=workflow_name,
            metadata={
                "warehouse": warehouse,
                "schedule": schedule,
                "after": after,
                "has_when": bool(when),
                "error_integration": error_integration,
            },
        )

        logger.info("TaskCompiler produced 1 artifact: %s", fqn)
        return [artifact]
