"""Logic extraction workflow — parse business logic from various formats.

Reuses:
    - ``databridge.blce.SQLExtractor``
    - ``databridge.blce.ExcelExtractor``
    - ``databridge.blce.DAXExtractor``
    - ``databridge.blce.MDXExtractor``
    - ``databridge.blce.PythonExtractor``
    - ``databridge.blce.PDFExtractor``

IKE integration (optional):
    - P6 Excel Wisdom: Deep formula graph analysis for Excel sources
    - P1 Knowledge Base: Ingest extracted patterns 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 LogicExtractionWorkflow(BaseWorkflow):
    """Extract business logic from SQL, Excel, DAX, MDX, Python, or PDF.

    Parses source files to identify formulas, calculations, filters,
    joins, and business rules for downstream reconciliation and
    model generation.

    When IKE is available and the source is Excel, IKE's P6 Excel
    Wisdom Extractor provides deep formula graph analysis beyond
    standard extraction.  Extracted patterns are ingested into P1 KB.

    Reuses:
        - ``databridge.blce.*Extractor`` classes
    """

    name = "blce.logic_extraction"
    category = "blce"
    description = "Extract business logic from SQL/Excel/DAX/MDX/Python/PDF sources"
    required_params = ["source_path"]
    optional_params = {
        "source_type": "auto",
        "ike_excel_wisdom": True,
        "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._extract(params, ctx)]
        if ctx and ctx.ike.available:
            # IKE P6: Deep Excel wisdom extraction for spreadsheet sources
            source = params.get("source_path", "")
            source_type = params.get("source_type", "auto")
            is_excel = source_type in ("excel", "xlsx", "xls") or (
                source_type == "auto" and source.lower().endswith((".xlsx", ".xls"))
            )
            if is_excel and params.get("ike_excel_wisdom"):
                steps.append(self._ike_excel_wisdom(params, ctx))
            # IKE P1: Ingest extracted logic patterns
            if params.get("ike_ingest"):
                steps.append(self._ike_ingest_patterns(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))
            steps.append(self._graph_update_entities(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",
            "Logic extraction is an analysis step; compile the "
            "extracted logic via WrightPipelineWorkflow instead",
        )

    @workflow_step("extract", "Parse and extract business logic")
    def _extract(self, params: Dict[str, Any], ctx: Optional[SDKContext] = None):
        # REUSE: Auto-detect source_type from extension, then:
        #   .sql -> databridge.blce.SQLExtractor().extract(source_path)
        #   .xlsx/.xls -> databridge.blce.ExcelExtractor().extract(source_path)
        #   .dax -> databridge.blce.DAXExtractor().extract(source_path)
        #   .mdx -> databridge.blce.MDXExtractor().extract(source_path)
        #   .py -> databridge.blce.PythonExtractor().extract(source_path)
        #   .pdf -> databridge.blce.PDFExtractor().extract(source_path)
        raise NotImplementedStubError(
            self.name,
            "extract",
            "databridge.blce.*Extractor().extract(source_path) — "
            "auto-detect from file extension",
        )

    @workflow_step("ike_excel_wisdom", "Deep Excel analysis via IKE P6")
    def _ike_excel_wisdom(self, params: Dict[str, Any], ctx: Optional[SDKContext] = None):
        # IKE P6: Excel Wisdom Extractor provides deep formula graph
        # analysis — builds a formula dependency graph, extracts
        # calculation patterns, detects circular refs, and identifies
        # business rule hierarchies embedded in spreadsheets.
        #
        # This augments the standard ExcelExtractor with:
        #   - Formula graph (DAG of cell dependencies)
        #   - Pattern extraction (common calculation templates)
        #   - Named range resolution
        #   - Cross-sheet reference tracking
        #
        # IKE P6 is accessed via IKE REST API at:
        #   POST /api/v1/excel/analyze
        raise NotImplementedStubError(
            self.name,
            "ike_excel_wisdom",
            "IKE P6 Excel Wisdom: POST /api/v1/excel/analyze — "
            "formula graph + pattern extraction + dependency DAG",
        )

    @workflow_step("ike_ingest_patterns", "Ingest extracted patterns into IKE KB")
    def _ike_ingest_patterns(self, params: Dict[str, Any], ctx: Optional[SDKContext] = None):
        # IKE P1: Ingest confirmed extraction patterns into the
        # institutional knowledge base.
        #
        # ctx.ike.ingest_knowledge(
        #     content=pattern_summary,
        #     source_type="run_result",
        #     tags=["blce", "logic_extraction", source_type],
        # )
        raise NotImplementedStubError(
            self.name,
            "ike_ingest_patterns",
            "ctx.ike.ingest_knowledge(content, source_type='run_result') — IKE P1 KB ingest",
        )

    # --- Graph integration ---

    @workflow_step("graph_record_lineage", "Record FORMULA and RULE nodes in lineage")
    def _graph_record_lineage(self, params: Dict[str, Any], ctx: Optional[SDKContext] = None):
        # ctx.graphs.record_lineage_node("sdk", formula_id, "EXTERNAL", description=formula)
        # ctx.graphs.record_lineage_node("sdk", rule_id, "EXTERNAL", description=rule_desc)
        raise NotImplementedStubError(
            self.name,
            "graph_record_lineage",
            "ctx.graphs.record_lineage_node — FORMULA + RULE nodes from extraction",
        )

    @workflow_step("graph_index_vectors", "Index extracted formulas in vector store")
    def _graph_index_vectors(self, params: Dict[str, Any], ctx: Optional[SDKContext] = None):
        # ctx.graphs.index_content(
        #     doc_id=f"logic_{formula_id}", content=formula_text,
        #     source_type="blce_formula", metadata={"source_type": source_type},
        # )
        raise NotImplementedStubError(
            self.name,
            "graph_index_vectors",
            "ctx.graphs.index_content(doc_id, content, 'blce_formula', metadata)",
        )

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

    @workflow_step("graph_update_entities", "Update entity clusters via entity linker")
    def _graph_update_entities(self, params: Dict[str, Any], ctx: Optional[SDKContext] = None):
        # ctx.graphs.link_entities_incremental(logic_dna_path)
        raise NotImplementedStubError(
            self.name,
            "graph_update_entities",
            "ctx.graphs.link_entities_incremental(logic_dna_path)",
        )
