import boto3
import typer
from botocore.exceptions import ClientError, NoCredentialsError
from flashenv.config import KEY_NAME, SG_NAME


def aws_connection() -> None:
    """Establishes a connection to AWS and verifies credentials."""
    sts = boto3.client("sts")
    try:
        res = sts.get_caller_identity()
        user_id = res.get("UserId")
        account = res.get("Account")
        typer.secho(f"✅ Connected to AWS Account: {account} (User: {user_id})", fg=typer.colors.GREEN)
    except NoCredentialsError:
        typer.secho("❌ Error: No AWS credentials found.", fg=typer.colors.RED, bold=True)
        raise typer.Exit(code=1) from None
    except ClientError as e:
        typer.secho(f"❌ AWS Client Error: {e}", fg=typer.colors.RED, bold=True)
        raise typer.Exit(code=1) from None


def upload_key_aws(public_key: bytes) -> None:
    """Uploads the public key to AWS EC2 as a Key Pair."""
    ec2 = boto3.client("ec2")
    try:
        ec2.import_key_pair(KeyName=KEY_NAME, PublicKeyMaterial=public_key)
        typer.secho(f"✅ Public key '{KEY_NAME}' uploaded on AWS.", fg=typer.colors.GREEN)
    except ClientError as e:
        error = e.response.get("Error")
        if error and error.get("Code") == "InvalidKeyPair.Duplicate":
            typer.secho("⚠️  SSH Key 'flashenv-key' already exists on AWS. Skipping.", fg=typer.colors.YELLOW)
        else:
            raise e


def delete_key_pair_aws(key_name: str = KEY_NAME) -> None:
    """Deletes the Key Pair from AWS EC2."""
    ec2 = boto3.client("ec2")
    try:
        typer.echo(f"🔑 Deleting key pair '{key_name}' from AWS...")
        ec2.delete_key_pair(KeyName=key_name)
        typer.secho(f"✅ AWS Key Pair '{key_name}' deleted.", fg=typer.colors.GREEN)

    except ClientError as e:
        typer.secho(f"❌ Failed to delete AWS key pair: {e}", fg=typer.colors.RED)


def create_security_group() -> str | None:
    """Creates a Security Group on AWS if it doesn't exist, and returns its ID."""
    ec2 = boto3.client("ec2")
    try:
        sgs = ec2.describe_security_groups(GroupNames=[SG_NAME])
        sg_id = sgs.get("SecurityGroups")[0].get("GroupId")
        typer.secho(f"✅ Security Group '{SG_NAME}' already exists ({sg_id}).", fg=typer.colors.GREEN)
        return sg_id
    except ClientError as e:
        error = e.response.get("Error")
        if error and error.get("Code") == "InvalidGroup.NotFound":
            try:
                typer.echo(f"🛡️ Creating Security Group '{SG_NAME}'...")
                response = ec2.create_security_group(GroupName=SG_NAME, Description="Managed by flashenv")
                sg_id = response["GroupId"]

                ec2.authorize_security_group_ingress(
                    GroupId=sg_id,
                    IpPermissions=[
                        {"IpProtocol": "tcp", "FromPort": 22, "ToPort": 22, "IpRanges": [{"CidrIp": "0.0.0.0/0"}]},
                        {"IpProtocol": "tcp", "FromPort": 80, "ToPort": 80, "IpRanges": [{"CidrIp": "0.0.0.0/0"}]},
                    ],
                )
                typer.secho(f"✅ Security Group created: {sg_id}", fg=typer.colors.GREEN)
                return sg_id
            except Exception as creation_error:
                typer.secho(f"❌ Failed to create Security Group: {creation_error}", fg=typer.colors.RED)
                raise typer.Exit(1) from None
        else:
            typer.secho(f"❌ Error checking Security Group: {e}", fg=typer.colors.RED)
            raise typer.Exit(1) from None


def get_latest_ami(ec2_client) -> str:
    response = ec2_client.describe_images(
        Owners=["amazon"],
        Filters=[
            {"Name": "name", "Values": ["al2023-ami-2023.*-kernel-6.1-x86_64"]},
            {"Name": "state", "Values": ["available"]},
        ],
    )
    images = sorted(response["Images"], key=lambda x: x["CreationDate"], reverse=True)
    if not images:
        raise Exception("Aucune AMI Amazon Linux 2023 trouvée.")
    return images[0]["ImageId"]


def get_flashenv_instances(ec2) -> list:
    """
    Finds all instances tagged/managed by flashenv via their Key Name.
    """
    try:
        response = ec2.describe_instances(
            Filters=[
                {"Name": "key-name", "Values": ["flashenv-key"]},
                {"Name": "instance-state-name", "Values": ["pending", "running", "stopping", "stopped"]},
            ]
        )
        ids = []
        for r in response["Reservations"]:
            for i in r["Instances"]:
                ids.append(i["InstanceId"])
        return ids
    except Exception:
        return []
