"""Full Platform Workflow Template — reusable end-to-end DataBridge pipeline.

Generalised from special_projects/enertia_full_platform_workflow.py.

Phases:
  0. Connect & load metadata from source
  1. Group tables by ERP prefix
  2. Build hierarchy from discovered tables
  3. Classify columns with DataShield AI
  4. Detect dimension vs fact tables (Kimball)
  5. Generate Wright pipelines from hierarchy
  6. Scaffold dbt project (staging + dimension models)
  7. Run data quality validations
  8. Set up observability baselines
  9. Generate artifact bundle
"""

from __future__ import annotations

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

from src.persistence.adapter import PersistenceAdapter
from src.persistence.file_adapter import FilePersistenceAdapter
from src.workflows.orchestrator import (
    OrchestratorConfig,
    PlatformOrchestrator,
    RunSummary,
)

logger = logging.getLogger(__name__)


class FullPlatformTemplate:
    """Reusable template for end-to-end DataBridge workflows.

    This template wraps ``PlatformOrchestrator`` with sensible defaults and
    a simplified API so users can kick off a complete engagement from a single
    call with just source + destination config.

    Example::

        template = FullPlatformTemplate(
            source_config={
                "source_type": "snowflake",
                "database": "ENERTIA_RAW",
                "schema": "ENERTIA_DBO",
                "tables": "*",
                "snowflake_connection": "aethon",
            },
            dest_config={
                "dbt_project_name": "enertia_dw",
                "output_dir": "data/workflow_runs/enertia",
            },
            options={
                "erp": "enertia",
                "sample_limit": 200,
                "dimension_threshold": 3,
            },
        )
        summary = template.run(skip_phases=[3, 5])  # skip AI classify + Wright
    """

    # Phase index to name mapping
    PHASE_NAMES = [
        "load_metadata",      # 0
        "group_tables",       # 1
        "hierarchy",          # 2
        "ai_classify",        # 3
        "detect_dimensions",  # 4
        "wright",             # 5
        "dbt",                # 6
        "quality",            # 7
        "observability",      # 8
        "artifact_bundle",    # 9
    ]

    def __init__(
        self,
        source_config: Dict[str, Any],
        dest_config: Optional[Dict[str, Any]] = None,
        options: Optional[Dict[str, Any]] = None,
        persistence: Optional[PersistenceAdapter] = None,
    ):
        """
        Args:
            source_config: Source connection details.
                Required keys: source_type, database, schema, tables.
                Optional: csv_folder, connection_string, snowflake_connection.
            dest_config: Output / destination config.
                Optional keys: dbt_project_name, output_dir.
            options: Tuning options.
                Optional keys: erp, sample_limit, min_overlap, dimension_threshold, focus_patterns.
            persistence: Custom persistence adapter (defaults to file-based).
        """
        dest = dest_config or {}
        opts = options or {}

        self._orch_config = OrchestratorConfig(
            source_type=source_config.get("source_type", "snowflake"),
            database=source_config.get("database", ""),
            schema=source_config.get("schema", ""),
            tables=source_config.get("tables", ""),
            csv_folder=source_config.get("csv_folder"),
            connection_string=source_config.get("connection_string"),
            snowflake_connection=source_config.get("snowflake_connection"),
            erp=opts.get("erp", "enertia"),
            sample_limit=opts.get("sample_limit", 200),
            min_overlap=opts.get("min_overlap", 0.5),
            dimension_threshold=opts.get("dimension_threshold", 3),
            focus_patterns=opts.get("focus_patterns"),
            dbt_project_name=dest.get("dbt_project_name"),
            dbt_run=dest.get("dbt_run", False),
            dbt_docs=dest.get("dbt_docs", False),
            output_dir=dest.get("output_dir", "data/workflow_runs"),
        )

        self._persistence = persistence or FilePersistenceAdapter(
            base_dir=str(Path(self._orch_config.output_dir) / "runs")
        )

    def run(
        self,
        skip_phases: Optional[List[int]] = None,
        only_phases: Optional[List[int]] = None,
    ) -> RunSummary:
        """Execute the full platform workflow.

        Args:
            skip_phases: List of phase indices (0-9) to skip.
            only_phases: If set, run ONLY these phase indices.

        Returns:
            RunSummary with per-phase results.
        """
        orch = PlatformOrchestrator(
            config=self._orch_config,
            persistence=self._persistence,
        )

        if only_phases is not None:
            phase_names = [
                self.PHASE_NAMES[i]
                for i in only_phases
                if 0 <= i < len(self.PHASE_NAMES)
            ]
            return orch.run(phases=phase_names)

        skip_names = []
        if skip_phases:
            skip_names = [
                self.PHASE_NAMES[i]
                for i in skip_phases
                if 0 <= i < len(self.PHASE_NAMES)
            ]
        return orch.run(skip=skip_names)

    def describe(self) -> Dict[str, Any]:
        """Return a human-readable description of the template configuration."""
        return {
            "template": "FullPlatformTemplate",
            "phases": [
                {"index": i, "name": name}
                for i, name in enumerate(self.PHASE_NAMES)
            ],
            "config": {
                "source_type": self._orch_config.source_type,
                "database": self._orch_config.database,
                "schema": self._orch_config.schema,
                "erp": self._orch_config.erp,
                "dbt_project_name": self._orch_config.dbt_project_name,
                "output_dir": self._orch_config.output_dir,
            },
        }
