"""
Create context step executor.
"""

import asyncio
from typing import Dict, Any, List
from merobox.commands.utils import get_node_rpc_url, console
from merobox.commands.context import create_context_via_admin_api
from merobox.commands.bootstrap.steps.base import BaseStep


class CreateContextStep(BaseStep):
    """Execute a create context step."""

    def _get_required_fields(self) -> List[str]:
        """
        Define which fields are required for this step.

        Returns:
            List of required field names
        """
        return ["node", "application_id"]

    def _validate_field_types(self) -> None:
        """
        Validate that fields have the correct types.
        """
        step_name = self.config.get(
            "name", f'Unnamed {self.config.get("type", "Unknown")} step'
        )

        # Validate node is a string
        if not isinstance(self.config.get("node"), str):
            raise ValueError(f"Step '{step_name}': 'node' must be a string")

        # Validate application_id is a string
        if not isinstance(self.config.get("application_id"), str):
            raise ValueError(f"Step '{step_name}': 'application_id' must be a string")

        # Validate params is JSON string if provided
        if "params" in self.config and not isinstance(self.config["params"], str):
            raise ValueError(f"Step '{step_name}': 'params' must be a JSON string")

    def _get_exportable_variables(self):
        """
        Define which variables this step can export.

        Note: These variables are NOT automatically exported.
        They must be explicitly specified in the 'outputs' configuration.

        Available variables from create_context API response:
        - contextId: Context ID (this is what the API actually returns)
        - memberPublicKey: Public key of the context member
        """
        return [
            (
                "contextId",
                "context_id_{node_name}",
                "Context ID - primary identifier for the created context",
            ),
            (
                "memberPublicKey",
                "context_member_public_key_{node_name}",
                "Public key of the context member",
            ),
        ]

    async def execute(
        self, workflow_results: Dict[str, Any], dynamic_values: Dict[str, Any]
    ) -> bool:
        node_name = self.config["node"]
        application_id = self._resolve_dynamic_value(
            self.config["application_id"], workflow_results, dynamic_values
        )

        # Validate export configuration
        if not self._validate_export_config():
            console.print(
                f"[yellow]⚠️  Context step export configuration validation failed[/yellow]"
            )

        initialization_params = None
        if "params" in self.config:
            try:
                import json

                params_json = self.config["params"]
                params_dict = json.loads(params_json)
                params_bytes = json.dumps(params_dict).encode("utf-8")
                initialization_params = list(params_bytes)
                console.print(
                    f"[blue]Using initialization params as bytes: {initialization_params[:50]}...[/blue]"
                )
            except json.JSONDecodeError as e:
                console.print(f"[red]Failed to parse params JSON: {str(e)}[/red]")
                return False

        # Get node RPC URL
        try:
            from merobox.commands.manager import CalimeroManager

            manager = CalimeroManager()
            rpc_url = get_node_rpc_url(node_name, manager)
        except Exception as e:
            console.print(
                f"[red]Failed to get RPC URL for node {node_name}: {str(e)}[/red]"
            )
            return False

        # Execute context creation
        result = await create_context_via_admin_api(
            rpc_url, application_id, initialization_params
        )

        # Log detailed API response
        console.print(f"[cyan]🔍 Context Creation API Response for {node_name}:[/cyan]")
        console.print(f"  Success: {result.get('success')}")
        console.print(f"  Data: {result.get('data')}")
        if not result.get("success"):
            console.print(f"  Error: {result.get('error')}")

        if result["success"]:
            # Check if the JSON-RPC response contains an error
            if self._check_jsonrpc_error(result["data"]):
                return False

            # Store result for later use
            step_key = f"context_{node_name}"
            workflow_results[step_key] = result["data"]

            # Export variables using the new standardized approach
            self._export_variables(result["data"], node_name, dynamic_values)

            # Legacy support: ensure context_id is always available for backward compatibility
            if f"context_id_{node_name}" not in dynamic_values:
                # Try to extract from the raw response as fallback
                if isinstance(result["data"], dict):
                    context_id = result["data"].get(
                        "id",
                        result["data"].get("contextId", result["data"].get("name")),
                    )
                    if context_id:
                        dynamic_values[f"context_id_{node_name}"] = context_id
                        console.print(
                            f"[blue]📝 Fallback: Captured context ID for {node_name}: {context_id}[/blue]"
                        )
                    else:
                        console.print(
                            f"[yellow]⚠️  No context ID found in response. Available keys: {list(result['data'].keys())}[/yellow]"
                        )
                else:
                    console.print(
                        f"[yellow]⚠️  Context result is not a dict: {type(result['data'])}[/yellow]"
                    )

            return True
        else:
            console.print(
                f"[red]Context creation failed: {result.get('error', 'Unknown error')}[/red]"
            )
            return False
