"""Terraform generation prompts for AI."""

from typing import Any, Dict, List, Optional

from ...models.generation import Layer, ResourceMap, TrackedResource
from ..property_maps import get_property_map

TERRAFORM_SYSTEM_PROMPT = """You are an expert Terraform engineer.
Generate Terraform configuration files from AWS resource descriptions.

## Guidelines

1. **Resource References**: Use Terraform references instead of hardcoded IDs
   - Example: Instead of "vpc-abc123", use `aws_vpc.main.id`
   - I'll provide a resource map showing available references

2. **Variable Usage**: Create variables for configurable values
   - Instance types, AMIs, counts, etc.
   - Use sensible defaults based on the inventory values

3. **Output Generation**: Create outputs for important resource attributes
   - IDs, ARNs, DNS names, endpoints

4. **Provider Configuration**: Do NOT include provider blocks - I'll handle that separately

5. **CRITICAL - Naming Convention**: You MUST use the EXACT Terraform name I provide for each resource.
   - Each resource description includes "Terraform name: `<name>`"
   - Use this EXACT name as the resource identifier
   - Example: If I say "Terraform name: `my_security_group_abc123`", use:
     `resource "aws_security_group" "my_security_group_abc123" { ... }`
   - NEVER use generic names like "default", "main", or "this"
   - The names I provide are already unique and validated

6. **Dependencies**: Use implicit dependencies via references
   - Explicit depends_on only when necessary

7. **Best Practices**:
   - Use count/for_each for similar resources
   - Add meaningful descriptions to variables
   - Group related resources together
   - Add comments for complex logic

## Output Format

Return ONLY valid HCL code. No markdown, no explanations, just the Terraform configuration.
"""


def get_terraform_system_prompt() -> str:
    """Get the system prompt for Terraform generation."""
    return TERRAFORM_SYSTEM_PROMPT


def format_layer_prompt(
    layer: Layer,
    resource_map: ResourceMap,
    previous_layers: Optional[List[str]] = None,
    lambda_code_paths: Optional[Dict[str, str]] = None,
) -> str:
    """Format prompt for generating a single layer.

    Args:
        layer: The layer to generate
        resource_map: Available resource references
        previous_layers: List of already generated layer file paths
        lambda_code_paths: Mapping of Lambda function names to extracted code file paths

    Returns:
        Formatted prompt string
    """
    resource_descriptions = []
    for resource in layer.resources:
        # Handle both TrackedResource objects and dicts
        if isinstance(resource, TrackedResource):
            tracked = resource
        else:
            tracked = TrackedResource.from_inventory(resource)
        desc = format_resource_for_prompt(tracked, lambda_code_paths)
        resource_descriptions.append(desc)

    resources_text = "\n\n".join(resource_descriptions)

    map_text = "## Available Resource References\n\n"
    map_text += "Use these Terraform references instead of hardcoded AWS IDs:\n\n"
    for aws_id, tf_ref in resource_map.id_to_ref.items():
        map_text += f"- `{aws_id}` -> `{tf_ref}`\n"

    context_text = ""
    if previous_layers:
        context_text = "\n\n## Previously Generated Layers\n\n"
        context_text += "These resources are already defined and available for reference:\n"
        for layer_file in previous_layers:
            context_text += f"- {layer_file}\n"

    lambda_code_text = ""
    if lambda_code_paths:
        lambda_code_text = "\n\n## Lambda Code Files\n\n"
        lambda_code_text += "Use `filename` attribute to reference these pre-extracted code archives:\n\n"
        for func_name, code_path in lambda_code_paths.items():
            lambda_code_text += f"- `{func_name}` -> `{code_path}`\n"

    prompt = f"""Generate Terraform configuration for the **{layer.name}** layer.

## Resources to Generate ({len(layer.resources)} resources)

{resources_text}

{map_text}
{context_text}
{lambda_code_text}

Generate complete, valid Terraform HCL for all resources above.
"""

    return prompt


def format_resource_for_prompt(
    resource: TrackedResource,
    lambda_code_paths: Optional[Dict[str, str]] = None,
) -> str:
    """Format a single resource for inclusion in prompt.

    Applies property filtering and formatting:
    - Removes computed/read-only properties
    - Converts CamelCase to snake_case
    - Applies resource-specific property maps

    Args:
        resource: The resource to format
        lambda_code_paths: Mapping of Lambda function names to extracted code file paths

    Returns:
        Formatted resource description
    """
    property_map = get_property_map(resource.resource_type)

    props = _filter_properties(resource.raw_config, property_map, resource.resource_type)

    lines = [
        f"### {resource.resource_type}: {resource.resource_id if hasattr(resource, 'resource_id') else resource.name}",
        f"Terraform name: `{resource.get_terraform_name()}`",
        f"Region: {resource.region}",
    ]

    if resource.arn:
        lines.append(f"ARN: {resource.arn}")

    if resource.tags:
        lines.append(f"Tags: {resource.tags}")

    # Add Lambda code file reference if available
    if lambda_code_paths and resource.name in lambda_code_paths:
        code_path = lambda_code_paths[resource.name]
        lines.append(f"\n**Lambda Code File:** `{code_path}`")
        lines.append('(Use `filename = "{code_path}"` in the aws_lambda_function resource)')

    lines.append("\n**Properties:**")
    lines.append("```json")

    import json

    lines.append(json.dumps(props, indent=2, default=str))

    lines.append("```")

    return "\n".join(lines)


def _filter_properties(
    raw_config: Dict[str, Any],
    property_map: Optional[Any],
    resource_type: str = "",
) -> Dict[str, Any]:
    """Filter properties for prompt inclusion.

    Uses property map's filter_properties if available, otherwise falls back
    to generic computed property filtering.

    Args:
        raw_config: Raw resource configuration from AWS API
        property_map: Property map module or dict (may have filter_properties function)
        resource_type: Resource type string for context

    Returns:
        Filtered dictionary suitable for Terraform generation prompt
    """
    # Try to use property map's filter_properties if available
    if property_map and hasattr(property_map, "filter_properties"):
        import inspect

        # Check if filter_properties accepts resource_type parameter
        sig = inspect.signature(property_map.filter_properties)
        if len(sig.parameters) > 1:
            return property_map.filter_properties(raw_config, resource_type)
        else:
            return property_map.filter_properties(raw_config)

    # Fallback to generic filtering if no property map
    computed_props = {
        "CreateTime",
        "CreationDate",
        "LastModified",
        "LastUpdated",
        "State",
        "Status",
        "Arn",
        "FunctionArn",
        "OwnerId",
        "RequesterId",
        "Attachments",
        "Association",
        "NetworkInterfaces",
        "BlockDeviceMappings",
        "StateReason",
        "StateTransitionReason",
        "Platform",
        "RootDeviceType",
        "VirtualizationType",
        "Monitoring",
        "Placement",
        "LaunchTime",
        "UsageOperation",
        "UsageOperationUpdateTime",
        "CapacityReservationSpecification",
        "HibernationOptions",
        "MetadataOptions",
        "EnclaveOptions",
        "BootMode",
        "CurrentInstanceBootMode",
        "PrivateDnsNameOptions",
        # IAM computed fields
        "RoleId",
        "PolicyId",
        "CreateDate",
        "UpdateDate",
        "AttachmentCount",
        "IsAttachable",
        "DefaultVersionId",
        "PolicyVersionList",
        # Lambda computed fields
        "CodeSize",
        "Version",
        "Revision",
        "PackageType",
        "StateReasonCode",
        "LastUpdateStatus",
        "LastUpdateStatusReason",
        "LastUpdateStatusReasonCode",
    }

    filtered = {}

    for key, value in raw_config.items():
        if key in computed_props:
            continue

        if value is None:
            continue

        if isinstance(value, (list, dict)) and not value:
            continue

        # Preserve internal data like _code for Lambda
        # (these contain important code reference info)
        if key.startswith("_"):
            # Only preserve known important internal keys
            if key in ("_code",):
                filtered[key] = value
            continue

        filtered[key] = value

    return filtered


def format_retry_prompt(
    original_code: str,
    validation_errors: List[str],
    layer: Layer,
    resource_map: ResourceMap,
) -> str:
    """Format prompt for retrying after validation failure.

    Args:
        original_code: The invalid Terraform code
        validation_errors: List of terraform validate errors
        layer: The layer being generated
        resource_map: Available resource references

    Returns:
        Formatted retry prompt
    """
    errors_text = "\n".join(f"- {err}" for err in validation_errors)

    prompt = f"""The Terraform code you generated has validation errors. Please fix them.

## Validation Errors

{errors_text}

## Original Code

```hcl
{original_code}
```

## Available Resource References

{_format_resource_map_text(resource_map)}

Generate the corrected Terraform code. Return ONLY valid HCL, no markdown or explanations.
"""

    return prompt


def _format_resource_map_text(resource_map: ResourceMap) -> str:
    """Format resource map as text for prompts."""
    lines = []
    for aws_id, tf_ref in resource_map.id_to_ref.items():
        lines.append(f"- `{aws_id}` -> `{tf_ref}`")
    return "\n".join(lines) if lines else "(No resource references available yet)"
