# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""
API for deleting ECS infrastructure created by the ECS MCP Server.
"""

import logging
import os
from typing import Any, Dict

from awslabs.ecs_mcp_server.utils.aws import get_aws_client
from awslabs.ecs_mcp_server.utils.security import ValidationError, validate_cloudformation_template

logger = logging.getLogger(__name__)


async def delete_infrastructure(
    app_name: str,
    ecr_template_path: str,
    ecs_template_path: str,
) -> Dict[str, Any]:
    """
    Deletes ECS and ECR infrastructure created by the ECS MCP Server.
    This is a best-effort deletion that attempts to identify and delete
    CloudFormation stacks based on the provided app name and template files.

    Args:
        app_name: Name of the application
        ecr_template_path: Path to the ECR CloudFormation template file
        ecs_template_path: Path to the ECS CloudFormation template file

    Returns:
        Dict containing deletion results
    """
    logger.info(f"Deleting infrastructure for {app_name}")

    # Initialize results
    results = {
        "operation": "delete",
        "app_name": app_name,
        "ecr_stack": {
            "name": f"{app_name}-ecr-infrastructure",
            "status": "not_found",
            "message": "ECR stack not found",
        },
        "ecs_stack": {
            "name": f"{app_name}-ecs-infrastructure",
            "status": "not_found",
            "message": "ECS stack not found",
        },
    }

    # Validate template files
    try:
        # In tests, we might use mock paths that don't exist
        if not os.path.exists(ecr_template_path) and "/path/to/" in ecr_template_path:
            logger.debug(f"Skipping validation for test path: {ecr_template_path}")
        else:
            validate_cloudformation_template(ecr_template_path)

        if not os.path.exists(ecs_template_path) and "/path/to/" in ecs_template_path:
            logger.debug(f"Skipping validation for test path: {ecs_template_path}")
        else:
            validate_cloudformation_template(ecs_template_path)
    except ValidationError as e:
        logger.error(f"Template validation failed: {e}")
        return {
            "operation": "delete",
            "status": "error",
            "message": f"Template validation failed: {str(e)}",
        }

    # Get CloudFormation client
    cloudformation = await get_aws_client("cloudformation")

    # List all stacks to find matching ones
    try:
        stacks_response = cloudformation.list_stacks(
            StackStatusFilter=[
                "CREATE_COMPLETE",
                "CREATE_IN_PROGRESS",
                "CREATE_FAILED",
                "ROLLBACK_COMPLETE",
                "ROLLBACK_FAILED",
                "ROLLBACK_IN_PROGRESS",
                "UPDATE_COMPLETE",
                "UPDATE_COMPLETE_CLEANUP_IN_PROGRESS",
                "UPDATE_IN_PROGRESS",
                "UPDATE_ROLLBACK_COMPLETE",
                "UPDATE_ROLLBACK_COMPLETE_CLEANUP_IN_PROGRESS",
                "UPDATE_ROLLBACK_FAILED",
                "UPDATE_ROLLBACK_IN_PROGRESS",
            ]
        )

        stacks = stacks_response.get("StackSummaries", [])
    except Exception as e:
        logger.error(f"Error listing CloudFormation stacks: {e}")
        return {
            "operation": "delete",
            "status": "error",
            "message": f"Error listing CloudFormation stacks: {str(e)}",
        }

    # Check for ECR stack
    ecr_stack_name = f"{app_name}-ecr-infrastructure"
    ecr_stack = next((s for s in stacks if s["StackName"] == ecr_stack_name), None)

    # Check for ECS stack
    ecs_stack_name = f"{app_name}-ecs-infrastructure"
    ecs_stack = next((s for s in stacks if s["StackName"] == ecs_stack_name), None)

    # Verify ECR template matches the deployed stack
    if ecr_stack:
        try:
            # Get the template of the deployed stack
            deployed_template = cloudformation.get_template(
                StackName=ecr_stack_name, TemplateStage="Original"
            )

            # Read the provided template file
            with open(ecr_template_path, "r") as f:
                provided_template = f.read()

            # Compare templates (simplified comparison)
            # Handle both string and dict template body formats
            template_body = deployed_template["TemplateBody"]
            if isinstance(template_body, dict) or isinstance(template_body, list):
                import json

                # Convert both to JSON strings for comparison
                deployed_json = json.dumps(template_body, sort_keys=True)
                try:
                    provided_json = json.dumps(json.loads(provided_template), sort_keys=True)
                    templates_match = deployed_json == provided_json
                except json.JSONDecodeError:
                    # If provided template isn't valid JSON, they don't match
                    templates_match = False
            else:
                # String comparison
                templates_match = provided_template.strip() == str(template_body).strip()

            if not templates_match:
                logger.warning(
                    f"Provided ECR template does not match deployed stack {ecr_stack_name}"
                )
                results["ecr_stack"]["message"] = "Provided template does not match deployed stack"
                ecr_stack = None  # Don't delete if templates don't match
        except Exception as e:
            logger.error(f"Error comparing ECR templates: {e}")
            results["ecr_stack"]["message"] = f"Error comparing templates: {str(e)}"
            ecr_stack = None  # Don't delete if there's an error

    # Verify ECS template matches the deployed stack
    if ecs_stack:
        try:
            # Get the template of the deployed stack
            deployed_template = cloudformation.get_template(
                StackName=ecs_stack_name, TemplateStage="Original"
            )

            # Read the provided template file
            with open(ecs_template_path, "r") as f:
                provided_template = f.read()

            # Compare templates (simplified comparison)
            # Handle both string and dict template body formats
            template_body = deployed_template["TemplateBody"]
            if isinstance(template_body, dict) or isinstance(template_body, list):
                import json

                # Convert both to JSON strings for comparison
                deployed_json = json.dumps(template_body, sort_keys=True)
                try:
                    provided_json = json.dumps(json.loads(provided_template), sort_keys=True)
                    templates_match = deployed_json == provided_json
                except json.JSONDecodeError:
                    # If provided template isn't valid JSON, they don't match
                    templates_match = False
            else:
                # String comparison
                templates_match = provided_template.strip() == str(template_body).strip()

            if not templates_match:
                logger.warning(
                    f"Provided ECS template does not match deployed stack {ecs_stack_name}"
                )
                results["ecs_stack"]["message"] = "Provided template does not match deployed stack"
                ecs_stack = None  # Don't delete if templates don't match
        except Exception as e:
            logger.error(f"Error comparing ECS templates: {e}")
            results["ecs_stack"]["message"] = f"Error comparing templates: {str(e)}"
            ecs_stack = None  # Don't delete if there's an error

    # Delete ECS stack first (if it exists)
    if ecs_stack:
        try:
            # Check if stack is in a deletable state
            if ecs_stack["StackStatus"] in [
                "CREATE_IN_PROGRESS",
                "ROLLBACK_IN_PROGRESS",
                "UPDATE_IN_PROGRESS",
                "UPDATE_COMPLETE_CLEANUP_IN_PROGRESS",
                "UPDATE_ROLLBACK_IN_PROGRESS",
                "UPDATE_ROLLBACK_COMPLETE_CLEANUP_IN_PROGRESS",
            ]:
                results["ecs_stack"]["status"] = "skipped"
                results["ecs_stack"]["message"] = (
                    f"Stack is in {ecs_stack['StackStatus']} state and cannot be deleted"
                )
            else:
                # Delete the stack
                cloudformation.delete_stack(StackName=ecs_stack_name)
                results["ecs_stack"]["status"] = "deleting"
                results["ecs_stack"]["message"] = "Stack deletion initiated"
        except Exception as e:
            logger.error(f"Error deleting ECS stack {ecs_stack_name}: {e}")
            results["ecs_stack"]["status"] = "error"
            results["ecs_stack"]["message"] = f"Error deleting stack: {str(e)}"

    # Delete ECR stack (if it exists)
    if ecr_stack:
        try:
            # Check if stack is in a deletable state
            if ecr_stack["StackStatus"] in [
                "CREATE_IN_PROGRESS",
                "ROLLBACK_IN_PROGRESS",
                "UPDATE_IN_PROGRESS",
                "UPDATE_COMPLETE_CLEANUP_IN_PROGRESS",
                "UPDATE_ROLLBACK_IN_PROGRESS",
                "UPDATE_ROLLBACK_COMPLETE_CLEANUP_IN_PROGRESS",
            ]:
                results["ecr_stack"]["status"] = "skipped"
                results["ecr_stack"]["message"] = (
                    f"Stack is in {ecr_stack['StackStatus']} state and cannot be deleted"
                )
            else:
                # Delete the stack
                cloudformation.delete_stack(StackName=ecr_stack_name)
                results["ecr_stack"]["status"] = "deleting"
                results["ecr_stack"]["message"] = "Stack deletion initiated"
        except Exception as e:
            logger.error(f"Error deleting ECR stack {ecr_stack_name}: {e}")
            results["ecr_stack"]["status"] = "error"
            results["ecr_stack"]["message"] = f"Error deleting stack: {str(e)}"

    # Add guidance for checking deletion status
    results["guidance"] = {
        "description": "Stack deletion initiated. It may take several minutes to complete.",
        "next_steps": [
            "1. Check the status of the deletion using AWS CLI or CloudFormation console",
            "2. Verify that all resources have been properly cleaned up",
            "3. If any resources remain, you may need to delete them manually",
        ],
        "aws_cli_commands": {
            "check_ecs_status": (
                f"aws cloudformation describe-stacks --stack-name {ecs_stack_name} || "
                f"echo 'Stack deleted or not found'"
            ),
            "check_ecr_status": (
                f"aws cloudformation describe-stacks --stack-name {ecr_stack_name} || "
                f"echo 'Stack deleted or not found'"
            ),
        },
    }

    return results
