"""
Unified MCP tools for Workflows (Phase 3C consolidation).

Consolidates 6 individual workflow tools into 2 action-dispatched tools:
- workflow_run(mode, ...) — 2 modes: platform, e2e_assessment
- workflow_manage(action, ...) — 4 actions: status, list_runs, list_phases, save_run

Original tool names are preserved as deprecation wrappers in mcp_tools.py.
"""

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

logger = logging.getLogger(__name__)

# ============================================================================
# Lazy singletons
# ============================================================================

_persistence = None


def _ensure_persistence(settings=None):
    global _persistence
    if _persistence is None:
        if settings and getattr(settings, "persistence_backend", None) == "snowflake" and getattr(settings, "persistence_snowflake_database", None):
            from src.persistence.snowflake_adapter import SnowflakePersistenceAdapter
            _persistence = SnowflakePersistenceAdapter(
                database=settings.persistence_snowflake_database,
                schema=getattr(settings, "persistence_snowflake_schema", "PUBLIC") or "PUBLIC",
            )
        else:
            from src.persistence.file_adapter import FilePersistenceAdapter
            _persistence = FilePersistenceAdapter()
    return _persistence


# ============================================================================
# workflow_run mode handlers
# ============================================================================

def _run_platform(settings, **kwargs) -> Dict[str, Any]:
    from .orchestrator import OrchestratorConfig, PlatformOrchestrator

    trust_attestation_raw = kwargs.get("trust_attestation")
    trust_attestation = None
    if trust_attestation_raw:
        try:
            trust_attestation = json.loads(trust_attestation_raw)
        except json.JSONDecodeError:
            return {"error": "Invalid trust_attestation JSON", "code": "TRUST_ATTESTATION_INVALID_FORMAT"}
    trust_lane = kwargs.get("trust_lane", "client_cortex_raw")

    config = OrchestratorConfig(
        source_type=kwargs.get("source_type", "snowflake"),
        database=kwargs.get("database", ""),
        schema=kwargs.get("schema", ""),
        tables=kwargs.get("tables", ""),
        csv_folder=kwargs.get("csv_folder"),
        erp=kwargs.get("erp", "enertia"),
        sample_limit=kwargs.get("sample_limit", 200),
        min_overlap=kwargs.get("min_overlap", 0.5),
        dimension_threshold=kwargs.get("dimension_threshold", 3),
        dbt_project_name=kwargs.get("dbt_project_name"),
        snowflake_connection=kwargs.get("snowflake_connection"),
    )

    skip = [s.strip() for s in (kwargs.get("skip_phases") or "").split(",") if s.strip()]
    persistence = _ensure_persistence(settings)
    orch = PlatformOrchestrator(config=config, persistence=persistence)
    orch.context["trust_attestation"] = trust_attestation
    orch.context["trust_lane"] = trust_lane
    summary = orch.run(skip=skip)
    return summary.to_dict()


def _run_e2e_assessment(settings, **kwargs) -> Dict[str, Any]:
    from .templates.e2e_assessment_template import E2EAssessmentTemplate

    trust_attestation_raw = kwargs.get("trust_attestation")
    trust_attestation = None
    if trust_attestation_raw:
        try:
            trust_attestation = json.loads(trust_attestation_raw)
        except json.JSONDecodeError:
            return {"error": "Invalid trust_attestation JSON", "code": "TRUST_ATTESTATION_INVALID_FORMAT"}
    trust_lane = kwargs.get("trust_lane", "client_cortex_raw")

    template = E2EAssessmentTemplate(
        source_config={
            "source_type": kwargs.get("source_type", "snowflake"),
            "database": kwargs.get("database", ""),
            "schema": kwargs.get("schema", ""),
            "tables": kwargs.get("tables", ""),
            "csv_folder": kwargs.get("csv_folder"),
            "snowflake_connection": kwargs.get("snowflake_connection"),
        },
        dest_config={
            "dest_db": kwargs.get("dest_db"),
            "dest_schema": kwargs.get("dest_schema"),
        },
        options={
            "erp": kwargs.get("erp", "enertia"),
            "sample_limit": kwargs.get("sample_limit", 200),
            "min_overlap": kwargs.get("min_overlap", 0.5),
            "dimension_threshold": kwargs.get("dimension_threshold", 3),
        },
        persistence=_ensure_persistence(settings),
    )

    skip = [s.strip() for s in (kwargs.get("skip_phases") or "").split(",") if s.strip()]
    summary = template.run(
        skip_phases=skip,
        trust_attestation=trust_attestation,
        trust_lane=trust_lane,
    )
    return summary.to_dict()


# ============================================================================
# workflow_manage action handlers
# ============================================================================

def _manage_status(settings, **kwargs) -> Dict[str, Any]:
    run_id = kwargs.get("run_id")
    if not run_id:
        return {"error": "run_id is required for 'status' action"}
    persistence = _ensure_persistence(settings)
    run = persistence.load_run(run_id)
    if not run:
        return {"error": f"Run {run_id} not found"}
    return run


def _manage_list_runs(settings, **kwargs) -> Dict[str, Any]:
    persistence = _ensure_persistence(settings)
    runs = persistence.list_runs(limit=kwargs.get("limit", 20))
    return {
        "runs": [
            {
                "run_id": r.get("run_id", "unknown"),
                "status": r.get("status", "unknown"),
                "started_at": r.get("started_at"),
                "total_duration_seconds": r.get("total_duration_seconds"),
            }
            for r in runs
        ],
        "count": len(runs),
    }


def _manage_list_phases(settings, **kwargs) -> Dict[str, Any]:
    from .orchestrator import PHASE_ORDER

    return {
        "phases": PHASE_ORDER,
        "count": len(PHASE_ORDER),
        "description": {
            "load_metadata": "Connect to source and discover tables/columns/relationships",
            "group_tables": "Group tables by ERP prefix into logical modules",
            "hierarchy": "Build DataBridge hierarchy from discovered tables",
            "ai_classify": "Classify columns using DataShield AI",
            "detect_dimensions": "Detect dimension vs fact tables (Kimball heuristics)",
            "wright": "Generate Wright 4-object pipelines from hierarchy",
            "dbt": "Scaffold dbt project with staging + dimension models",
            "quality": "Generate and run data quality expectations",
            "observability": "Set up observability baselines and alert rules",
            "artifact_bundle": "Generate run artifacts (HTML report, JSON summary, manifest)",
        },
    }


def _manage_save_run(settings, **kwargs) -> Dict[str, Any]:
    run_id = kwargs.get("run_id")
    summary_json = kwargs.get("summary_json")
    if not run_id or not summary_json:
        return {"error": "run_id and summary_json are required for 'save_run' action"}
    try:
        summary = json.loads(summary_json)
    except json.JSONDecodeError:
        return {"error": "Invalid JSON"}

    persistence = _ensure_persistence(settings)
    persistence.save_run(run_id, summary)
    return {"status": "saved", "run_id": run_id}


# ============================================================================
# Action dispatch dictionaries
# ============================================================================

_RUN_MODES = {
    "platform": _run_platform,
    "e2e_assessment": _run_e2e_assessment,
}

_MANAGE_ACTIONS = {
    "status": _manage_status,
    "list_runs": _manage_list_runs,
    "list_phases": _manage_list_phases,
    "save_run": _manage_save_run,
}


# ============================================================================
# Unified dispatch functions
# ============================================================================

def dispatch_workflow_run(settings, mode: str, **kwargs) -> Dict[str, Any]:
    """Dispatch a workflow_run mode."""
    handler = _RUN_MODES.get(mode)
    if not handler:
        return {
            "error": f"Unknown mode: '{mode}'",
            "valid_modes": sorted(_RUN_MODES.keys()),
        }
    try:
        return handler(settings, **kwargs)
    except Exception as e:
        logger.error(f"workflow_run({mode}) failed: {e}")
        return {"error": f"workflow_run({mode}) failed: {e}"}


def dispatch_workflow_manage(settings, action: str, **kwargs) -> Dict[str, Any]:
    """Dispatch a workflow_manage action."""
    handler = _MANAGE_ACTIONS.get(action)
    if not handler:
        return {
            "error": f"Unknown action: '{action}'",
            "valid_actions": sorted(_MANAGE_ACTIONS.keys()),
        }
    try:
        return handler(settings, **kwargs)
    except Exception as e:
        logger.error(f"workflow_manage({action}) failed: {e}")
        return {"error": f"workflow_manage({action}) failed: {e}"}


# ============================================================================
# Registration
# ============================================================================

def register_unified_workflow_tools(mcp, settings):
    """Register the 2 unified workflow MCP tools."""

    @mcp.tool()
    def workflow_run(
        mode: str,
        source_type: Optional[str] = "snowflake",
        database: Optional[str] = "",
        schema: Optional[str] = "",
        tables: Optional[str] = "",
        csv_folder: Optional[str] = None,
        erp: Optional[str] = "enertia",
        sample_limit: Optional[int] = 200,
        min_overlap: Optional[float] = 0.5,
        dimension_threshold: Optional[int] = 3,
        dbt_project_name: Optional[str] = None,
        skip_phases: Optional[str] = None,
        snowflake_connection: Optional[str] = None,
        dest_db: Optional[str] = None,
        dest_schema: Optional[str] = None,
        trust_attestation: Optional[str] = None,
        trust_lane: Optional[str] = None,
    ) -> Dict[str, Any]:
        """
        Unified workflow execution tool. Replaces 2 individual run tools.

        Modes:
        - platform: Run 10-phase DataBridge platform workflow
        - e2e_assessment: Run 15-phase E2E assessment workflow (adds bus_matrix, dm_load, etc.)

        Both modes share: source_type, database, schema, tables, csv_folder, erp,
        sample_limit, skip_phases, snowflake_connection.
        e2e_assessment also accepts: dest_db, dest_schema.
        trust_attestation accepts JSON string payload to enforce trust lane checks.
        trust_lane defaults to client_cortex_raw.

        Returns:
            Workflow run summary dict
        """
        return dispatch_workflow_run(settings, mode, **{
            k: v for k, v in {
                "source_type": source_type, "database": database, "schema": schema,
                "tables": tables, "csv_folder": csv_folder, "erp": erp,
                "sample_limit": sample_limit, "min_overlap": min_overlap,
                "dimension_threshold": dimension_threshold,
                "dbt_project_name": dbt_project_name, "skip_phases": skip_phases,
                "snowflake_connection": snowflake_connection,
                "dest_db": dest_db, "dest_schema": dest_schema,
                "trust_attestation": trust_attestation, "trust_lane": trust_lane,
            }.items() if v is not None
        })

    @mcp.tool()
    def workflow_manage(
        action: str,
        run_id: Optional[str] = None,
        summary_json: Optional[str] = None,
        limit: Optional[int] = 20,
    ) -> Dict[str, Any]:
        """
        Unified workflow management tool. Replaces 4 individual tools.

        Actions:
        - status: Get status of a workflow run (requires run_id)
        - list_runs: List recent workflow runs (optional limit)
        - list_phases: List all available workflow phases
        - save_run: Save a workflow run summary (requires run_id, summary_json)

        Returns:
            Action-specific result dict
        """
        return dispatch_workflow_manage(settings, action, **{
            k: v for k, v in {
                "run_id": run_id, "summary_json": summary_json, "limit": limit,
            }.items() if v is not None
        })

    logger.info("Registered 2 unified workflow tools: workflow_run, workflow_manage")
