"""
ETL Executor Tools for Autonomous Agent

Provides ETL execution capabilities for the data factory:
- Run specific ETL modules
- Run all ETLs
- Check ETL status after execution
"""

from __future__ import annotations

import asyncio
import importlib
from datetime import date, datetime, timezone
from typing import Any

from ..types import AgentPriority


class ETLExecutorTools:
    """
    ETL execution tools for the autonomous agent

    Token consumption: 0 (pure Python execution)
    """

    # Available ETL modules
    AVAILABLE_MODULES = [
        "ga4",
        "bsr",
        "visibility",
        "citation",
        "attribution",
        "content_attribution",
        "voc_reddit",
        "voc_trustpilot",
        "ontology",
        "bsr_voc_linking",
    ]

    # Module to function mapping
    MODULE_FUNCTIONS = {
        "ga4": ("workflows.etl.ga4_etl", "ga4_t1_etl"),
        "bsr": ("workflows.etl.bsr_etl", "bsr_t1_etl"),
        "visibility": ("workflows.etl.visibility_etl", "visibility_t1_etl"),
        "citation": ("workflows.etl.citation_etl", "citation_t1_etl"),
        "attribution": ("workflows.etl.attribution_etl", "attribution_t1_etl"),
        "content_attribution": ("workflows.etl.content_attribution_etl", "content_attribution_t1_etl"),
        "voc_reddit": ("workflows.etl.voc_reddit_etl", "voc_reddit_t1_etl"),
        "voc_trustpilot": ("workflows.etl.voc_trustpilot_etl", "voc_trustpilot_t1_etl"),
        "ontology": ("workflows.etl.ontology_etl", "ontology_t1_etl"),
        "bsr_voc_linking": ("workflows.etl.bsr_voc_linking_etl", "bsr_voc_linking_t1_etl"),
    }

    async def run_etl(
        self,
        module: str,
        target_date: date | None = None,
        priority: AgentPriority = AgentPriority.MEDIUM
    ) -> dict[str, Any]:
        """
        Run a specific ETL module

        Args:
            module: ETL module name (e.g., 'ga4', 'bsr')
            target_date: Target date for ETL (default: yesterday)
            priority: Execution priority

        Returns:
            ETL execution result
        """
        if module not in self.AVAILABLE_MODULES:
            return {
                "success": False,
                "module": module,
                "error": f"Unknown module: {module}. Available: {', '.join(self.AVAILABLE_MODULES)}",
            }

        try:
            # Get module and function names
            module_path, func_name = self.MODULE_FUNCTIONS.get(module, (None, None))

            if not module_path:
                return {
                    "success": False,
                    "module": module,
                    "error": f"No ETL function defined for module: {module}",
                }

            # Dynamically import the module
            etl_module = importlib.import_module(f"src.{module_path}")
            etl_function = getattr(etl_module, func_name)

            # Execute ETL
            start_time = datetime.now(timezone.utc)

            if target_date:
                result = await etl_function(target_date)
            else:
                result = await etl_function()

            end_time = datetime.now(timezone.utc)
            duration_seconds = (end_time - start_time).total_seconds()

            return {
                "success": result.success if hasattr(result, 'success') else True,
                "module": module,
                "target_date": str(target_date) if target_date else str(result.target_date) if hasattr(result, 'target_date') else None,
                "records_collected": result.records_collected if hasattr(result, 'records_collected') else 0,
                "records_stored": result.records_stored if hasattr(result, 'records_stored') else 0,
                "duration_seconds": duration_seconds,
                "errors": result.errors if hasattr(result, 'errors') else [],
                "executed_at": end_time.isoformat(),
            }

        except Exception as e:
            return {
                "success": False,
                "module": module,
                "error": str(e),
                "executed_at": datetime.now(timezone.utc).isoformat(),
            }

    async def run_multiple_etls(
        self,
        modules: list[str],
        parallel: bool = False,
        target_date: date | None = None
    ) -> dict[str, Any]:
        """
        Run multiple ETL modules

        Args:
            modules: List of module names
            parallel: Whether to run in parallel
            target_date: Target date for all ETLs

        Returns:
            Aggregated results
        """
        results = {}
        total_success = 0
        total_failed = 0

        if parallel:
            # Run in parallel
            tasks = [
                self.run_etl(module, target_date)
                for module in modules
            ]
            task_results = await asyncio.gather(*tasks, return_exceptions=True)

            for module, result in zip(modules, task_results):
                if isinstance(result, Exception):
                    results[module] = {"success": False, "error": str(result)}
                    total_failed += 1
                else:
                    results[module] = result
                    if result.get("success"):
                        total_success += 1
                    else:
                        total_failed += 1
        else:
            # Run sequentially
            for module in modules:
                result = await self.run_etl(module, target_date)
                results[module] = result
                if result.get("success"):
                    total_success += 1
                else:
                    total_failed += 1

        return {
            "success": total_failed == 0,
            "total_modules": len(modules),
            "successful": total_success,
            "failed": total_failed,
            "results": results,
            "executed_at": datetime.now(timezone.utc).isoformat(),
        }

    async def run_all_etls(
        self,
        target_date: date | None = None,
        skip_modules: list[str] | None = None
    ) -> dict[str, Any]:
        """
        Run all ETL modules

        Args:
            target_date: Target date for all ETLs
            skip_modules: Modules to skip

        Returns:
            Aggregated results
        """
        modules_to_run = [
            m for m in self.AVAILABLE_MODULES
            if not skip_modules or m not in skip_modules
        ]

        return await self.run_multiple_etls(
            modules=modules_to_run,
            parallel=False,  # Sequential for safety
            target_date=target_date,
        )

    def list_available_modules(self) -> list[dict[str, str]]:
        """List all available ETL modules"""
        module_info = {
            "ga4": "Google Analytics 4 traffic and transactions",
            "bsr": "Amazon Best Seller Rankings",
            "visibility": "AI platform visibility monitoring",
            "citation": "Citation tracking from authority sites",
            "attribution": "Shopify + GA4 revenue attribution",
            "content_attribution": "AI platform → revenue attribution",
            "voc_reddit": "Voice of Customer from Reddit",
            "voc_trustpilot": "Voice of Customer from Trustpilot",
            "ontology": "Brand knowledge graph enrichment",
            "bsr_voc_linking": "BSR-VOC content linking",
        }

        return [
            {"module": m, "description": module_info.get(m, "No description")}
            for m in self.AVAILABLE_MODULES
        ]


# Tool definitions for Claude Agent SDK
ETL_EXECUTOR_TOOLS = [
    {
        "name": "run_etl",
        "description": "Run a specific ETL module to collect and process data. Use this when a pipeline is stale or needs refresh.",
        "input_schema": {
            "type": "object",
            "properties": {
                "module": {
                    "type": "string",
                    "description": "ETL module name",
                    "enum": ETLExecutorTools.AVAILABLE_MODULES,
                },
                "target_date": {
                    "type": "string",
                    "description": "Target date in YYYY-MM-DD format (optional, defaults to yesterday)",
                },
                "priority": {
                    "type": "string",
                    "description": "Execution priority",
                    "enum": ["low", "medium", "high", "critical"],
                    "default": "medium",
                },
            },
            "required": ["module"]
        }
    },
    {
        "name": "run_multiple_etls",
        "description": "Run multiple ETL modules at once.",
        "input_schema": {
            "type": "object",
            "properties": {
                "modules": {
                    "type": "array",
                    "items": {"type": "string"},
                    "description": "List of ETL module names to run",
                },
                "parallel": {
                    "type": "boolean",
                    "description": "Whether to run in parallel (default: false for safety)",
                    "default": False,
                },
                "target_date": {
                    "type": "string",
                    "description": "Target date in YYYY-MM-DD format",
                },
            },
            "required": ["modules"]
        }
    },
    {
        "name": "list_available_modules",
        "description": "List all available ETL modules and their descriptions.",
        "input_schema": {
            "type": "object",
            "properties": {},
            "required": []
        }
    },
]
