"""Data profiling workflow.

Reuses:
    - ``databridge.profiler.profile_data(source_path)``
    - ``databridge.profiler.generate_expectation_suite(...)``

IKE integration (optional):
    - P1 Knowledge Base: Ingest profiling results into institutional memory
"""

from __future__ import annotations

from typing import Any, Dict, List, Optional

from databridge_core.sdk.core.context import SDKContext
from databridge_core.sdk.core.exceptions import NotImplementedStubError
from databridge_core.sdk.core.types import CompiledArtifact, Result
from databridge_core.sdk.workflows.base import BaseWorkflow
from databridge_core.sdk.workflows.result import WorkflowResult
from databridge_core.sdk.workflows.step import workflow_step


class ProfileWorkflow(BaseWorkflow):
    """Profile a data source to understand structure, quality, and patterns.

    When IKE is available, profiling results are ingested into IKE's
    P1 knowledge base so future runs benefit from institutional memory
    of data source characteristics.

    Reuses:
        - ``databridge.profiler.profile_data(source_path: str) -> Dict``
        - ``databridge.profiler.generate_expectation_suite(...)``
        - ``databridge.profiler.detect_schema_drift(...)``
    """

    name = "data_cleaning.profiling"
    category = "data_cleaning"
    description = "Profile data source for structure, quality, and drift detection"
    required_params = ["source_path"]
    optional_params = {
        "generate_expectations": False,
        "drift_baseline_path": None,
        "ike_ingest": True,
    }

    def validate(self, params: Dict[str, Any]) -> Dict[str, Any]:
        self._check_required(params)
        return self._apply_defaults(params)

    def execute(
        self, params: Dict[str, Any], ctx: Optional[SDKContext] = None
    ) -> Result:
        steps = [
            self._profile(params, ctx),
        ]
        if params.get("generate_expectations"):
            steps.append(self._expectations(params, ctx))
        if params.get("drift_baseline_path"):
            steps.append(self._drift_check(params, ctx))
        # IKE P1: Ingest profile results into institutional KB
        if params.get("ike_ingest") and ctx and ctx.ike.available:
            steps.append(self._ike_ingest_profile(params, ctx))
        # Graph integration
        if ctx and ctx.graphs.available:
            steps.append(self._graph_record_lineage(params, ctx))
            steps.append(self._graph_index_vectors(params, ctx))
            steps.append(self._graph_ingest_kb(params, ctx))
        return WorkflowResult.from_steps(self.name, steps)

    def compile_to_snowflake(
        self, params: Dict[str, Any], ctx: Optional[SDKContext] = None
    ) -> List[CompiledArtifact]:
        raise NotImplementedStubError(
            self.name,
            "compile_to_snowflake",
            "Generate a Snowflake VIEW with profiling stats using "
            "APPROX_PERCENTILE, HLL, etc.",
        )

    @workflow_step("profile", "Run data profiling")
    def _profile(self, params: Dict[str, Any], ctx: Optional[SDKContext] = None):
        # REUSE: databridge.profiler.profile_data(params["source_path"])
        raise NotImplementedStubError(
            self.name,
            "profile",
            "databridge.profiler.profile_data(source_path)",
        )

    @workflow_step("expectations", "Generate expectation suite")
    def _expectations(self, params: Dict[str, Any], ctx: Optional[SDKContext] = None):
        # REUSE: databridge.profiler.generate_expectation_suite(...)
        raise NotImplementedStubError(
            self.name,
            "expectations",
            "databridge.profiler.generate_expectation_suite(source_path, suite_name)",
        )

    @workflow_step("drift_check", "Detect schema drift")
    def _drift_check(self, params: Dict[str, Any], ctx: Optional[SDKContext] = None):
        # REUSE: databridge.profiler.detect_schema_drift(source_a, source_b)
        raise NotImplementedStubError(
            self.name,
            "drift_check",
            "databridge.profiler.detect_schema_drift(baseline_path, current_path)",
        )

    @workflow_step("ike_ingest_profile", "Ingest profiling results into IKE KB")
    def _ike_ingest_profile(self, params: Dict[str, Any], ctx: Optional[SDKContext] = None):
        # IKE P1: Ingest profiling results (column stats, data types,
        # quality metrics) into the institutional knowledge base.
        # Future profiling runs benefit from historical context.
        #
        # ctx.ike.ingest_knowledge(
        #     content=f"Profile of {params['source_path']}: {profile_summary}",
        #     source_type="run_result",
        #     tags=["profiling", source_name],
        # )
        raise NotImplementedStubError(
            self.name,
            "ike_ingest_profile",
            "ctx.ike.ingest_knowledge(content, source_type='run_result') — IKE P1 KB ingest",
        )

    # --- Graph integration ---

    @workflow_step("graph_record_lineage", "Record TABLE and COLUMN nodes in lineage")
    def _graph_record_lineage(self, params: Dict[str, Any], ctx: Optional[SDKContext] = None):
        # ctx.graphs.record_lineage_node("sdk", table_name, "TABLE",
        #     columns=[{"name": col, "data_type": dtype} for col, dtype in profile])
        raise NotImplementedStubError(
            self.name,
            "graph_record_lineage",
            "ctx.graphs.record_lineage_node — TABLE + COLUMN nodes from profile",
        )

    @workflow_step("graph_index_vectors", "Index profile stats in vector store")
    def _graph_index_vectors(self, params: Dict[str, Any], ctx: Optional[SDKContext] = None):
        # ctx.graphs.index_content(
        #     doc_id=f"profile_{source}", content=profile_summary,
        #     source_type="profile_stats", metadata={...},
        # )
        raise NotImplementedStubError(
            self.name,
            "graph_index_vectors",
            "ctx.graphs.index_content(doc_id, content, 'profile_stats', metadata)",
        )

    @workflow_step("graph_ingest_kb", "Ingest column metadata into KB graph")
    def _graph_ingest_kb(self, params: Dict[str, Any], ctx: Optional[SDKContext] = None):
        # ctx.graphs.ingest_kb_nodes(
        #     nodes=[{"id": col_name, "type": "Column", "properties": {"data_type": ...}}],
        # )
        raise NotImplementedStubError(
            self.name,
            "graph_ingest_kb",
            "ctx.graphs.ingest_kb_nodes(nodes) — column metadata as KB graph nodes",
        )
