"""Fuzzy match workflow.

Reuses:
    - ``databridge.reconciler.fuzzy_match_columns(source_a_path, source_b_path, column_a, column_b, threshold, limit)``

IKE integration (optional):
    - P4 Scoring: Calibrate match confidence via Thompson + SPRT + Platt
"""

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 FuzzyMatchWorkflow(BaseWorkflow):
    """Fuzzy-match columns between two data sources.

    When IKE is available, match scores are calibrated through
    IKE's P4 scoring engine for improved confidence assessment.

    Reuses:
        - ``databridge.reconciler.fuzzy_match_columns(source_a_path, source_b_path, column_a, column_b, threshold, limit)``
    """

    name = "reconciliation.fuzzy_match"
    category = "reconciliation"
    description = "Fuzzy-match columns between two sources using similarity scoring"
    required_params = ["source_a_path", "source_b_path", "column_a", "column_b"]
    optional_params = {
        "threshold": 80,
        "limit": 10,
        "ike_scoring": 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._match(params, ctx)]
        # IKE P4: Calibrate match scores
        if params.get("ike_scoring") and ctx and ctx.ike.available:
            steps.append(self._ike_calibrate_scores(params, ctx))
        # Graph integration
        if ctx and ctx.graphs.available:
            steps.append(self._graph_record_lineage(params, ctx))
            steps.append(self._graph_record_evidence(params, ctx))
            steps.append(self._graph_index_vectors(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 Snowflake EDITDISTANCE / JAROWINKLER_SIMILARITY UDF",
        )

    @workflow_step("fuzzy_match", "Run fuzzy column matching")
    def _match(self, params: Dict[str, Any], ctx: Optional[SDKContext] = None):
        # REUSE: databridge.reconciler.fuzzy_match_columns(
        #     source_a_path=params["source_a_path"],
        #     source_b_path=params["source_b_path"],
        #     column_a=params["column_a"],
        #     column_b=params["column_b"],
        #     threshold=params["threshold"],
        #     limit=params["limit"],
        # )
        raise NotImplementedStubError(
            self.name,
            "fuzzy_match",
            "databridge.reconciler.fuzzy_match_columns(source_a_path, source_b_path, column_a, column_b, threshold, limit)",
        )

    @workflow_step("ike_calibrate_scores", "Calibrate match scores via IKE P4")
    def _ike_calibrate_scores(self, params: Dict[str, Any], ctx: Optional[SDKContext] = None):
        # IKE P4: Calibrate fuzzy match scores through Thompson
        # Sampling + Platt calibration for improved confidence.
        #
        # ctx.ike.batch_score([
        #     {"bandit_id": "fuzzy_match",
        #      "item_id": f"{value_a}::{value_b}",
        #      "raw_confidence": similarity_score / 100.0}
        #     for value_a, value_b, similarity_score in match_results
        # ])
        raise NotImplementedStubError(
            self.name,
            "ike_calibrate_scores",
            "ctx.ike.batch_score(matches) — IKE P4 Platt-calibrated scoring",
        )

    # --- Graph integration ---

    @workflow_step("graph_record_lineage", "Record MAPPING_DECISION nodes and MAPPED_TO edges")
    def _graph_record_lineage(self, params: Dict[str, Any], ctx: Optional[SDKContext] = None):
        # ctx.graphs.record_lineage_node("sdk", f"fuzzy_match:{col_a}_{col_b}", "EXTERNAL")
        # ctx.graphs.record_lineage_edge("sdk", source_a, match_node, "JOIN")
        raise NotImplementedStubError(
            self.name,
            "graph_record_lineage",
            "ctx.graphs.record_lineage_node/edge — MAPPING_DECISION + MAPPED_TO edges",
        )

    @workflow_step("graph_record_evidence", "Record match evidence in evidence trail")
    def _graph_record_evidence(self, params: Dict[str, Any], ctx: Optional[SDKContext] = None):
        # ctx.graphs.record_evidence(
        #     account_id=value_a, hierarchy_node_id=value_b,
        #     method="fuzzy_match", confidence=score/100.0,
        #     evidence_sources=[{"content": f"{value_a} ~ {value_b}", ...}],
        # )
        raise NotImplementedStubError(
            self.name,
            "graph_record_evidence",
            "ctx.graphs.record_evidence(account_id, hierarchy_node_id, 'fuzzy_match', confidence, ...)",
        )

    @workflow_step("graph_index_vectors", "Index match pairs in vector store")
    def _graph_index_vectors(self, params: Dict[str, Any], ctx: Optional[SDKContext] = None):
        # ctx.graphs.index_content(
        #     doc_id=f"fuzzy_{run_id}", content=match_summary,
        #     source_type="fuzzy_match", metadata={...},
        # )
        raise NotImplementedStubError(
            self.name,
            "graph_index_vectors",
            "ctx.graphs.index_content(doc_id, content, 'fuzzy_match', metadata)",
        )
