# LocalStack Resource Provider Scaffolding v2
from __future__ import annotations

import logging
from pathlib import Path
from typing import TypedDict

import localstack.services.cloudformation.provider_utils as util
from localstack.services.cloudformation.resource_provider import (
    OperationStatus,
    ProgressEvent,
    ResourceProvider,
    ResourceRequest,
)
from localstack.utils.aws import arns

LOG = logging.getLogger(__name__)

# simple mock state
default_repos_per_stack = {}


class ECRRepositoryProperties(TypedDict):
    Arn: str | None
    EncryptionConfiguration: EncryptionConfiguration | None
    ImageScanningConfiguration: ImageScanningConfiguration | None
    ImageTagMutability: str | None
    LifecyclePolicy: LifecyclePolicy | None
    RepositoryName: str | None
    RepositoryPolicyText: dict | str | None
    RepositoryUri: str | None
    Tags: list[Tag] | None


class LifecyclePolicy(TypedDict):
    LifecyclePolicyText: str | None
    RegistryId: str | None


class Tag(TypedDict):
    Key: str | None
    Value: str | None


class ImageScanningConfiguration(TypedDict):
    ScanOnPush: bool | None


class EncryptionConfiguration(TypedDict):
    EncryptionType: str | None
    KmsKey: str | None


REPEATED_INVOCATION = "repeated_invocation"


class ECRRepositoryProvider(ResourceProvider[ECRRepositoryProperties]):
    TYPE = "AWS::ECR::Repository"  # Autogenerated. Don't change
    SCHEMA = util.get_schema_path(Path(__file__))  # Autogenerated. Don't change

    def create(
        self,
        request: ResourceRequest[ECRRepositoryProperties],
    ) -> ProgressEvent[ECRRepositoryProperties]:
        """
        Create a new resource.

        Primary identifier fields:
          - /properties/RepositoryName

        Create-only properties:
          - /properties/RepositoryName
          - /properties/EncryptionConfiguration
          - /properties/EncryptionConfiguration/EncryptionType
          - /properties/EncryptionConfiguration/KmsKey

        Read-only properties:
          - /properties/Arn
          - /properties/RepositoryUri

        IAM permissions required:
          - ecr:CreateRepository
          - ecr:PutLifecyclePolicy
          - ecr:SetRepositoryPolicy
          - ecr:TagResource
          - kms:DescribeKey
          - kms:CreateGrant
          - kms:RetireGrant

        """
        model = request.desired_state
        model["RepositoryName"] = (
            model.get("RepositoryName")
            or util.generate_default_name(request.stack_name, request.logical_resource_id).lower()
        )

        default_repos_per_stack[request.stack_name] = model["RepositoryName"]
        LOG.warning(
            "Creating a Mock ECR Repository for CloudFormation. This is only intended to be used for allowing a successful CDK bootstrap and does not provision any underlying ECR repository."
        )
        model.update(
            {
                "Arn": arns.ecr_repository_arn(
                    model["RepositoryName"], request.account_id, request.region_name
                ),
                "RepositoryUri": "http://localhost:4566",
                "ImageTagMutability": "MUTABLE",
                "ImageScanningConfiguration": {"scanOnPush": True},
            }
        )
        return ProgressEvent(
            status=OperationStatus.SUCCESS,
            resource_model=model,
            custom_context=request.custom_context,
        )

    def read(
        self,
        request: ResourceRequest[ECRRepositoryProperties],
    ) -> ProgressEvent[ECRRepositoryProperties]:
        """
        Fetch resource information

        IAM permissions required:
          - ecr:DescribeRepositories
          - ecr:GetLifecyclePolicy
          - ecr:GetRepositoryPolicy
          - ecr:ListTagsForResource
        """
        raise NotImplementedError

    def delete(
        self,
        request: ResourceRequest[ECRRepositoryProperties],
    ) -> ProgressEvent[ECRRepositoryProperties]:
        """
        Delete a resource

        IAM permissions required:
          - ecr:DeleteRepository
          - kms:RetireGrant
        """
        if default_repos_per_stack.get(request.stack_name):
            del default_repos_per_stack[request.stack_name]

        return ProgressEvent(
            status=OperationStatus.SUCCESS,
            resource_model=request.desired_state,
            custom_context=request.custom_context,
        )

    def update(
        self,
        request: ResourceRequest[ECRRepositoryProperties],
    ) -> ProgressEvent[ECRRepositoryProperties]:
        """
        Update a resource

        IAM permissions required:
          - ecr:PutLifecyclePolicy
          - ecr:SetRepositoryPolicy
          - ecr:TagResource
          - ecr:UntagResource
          - ecr:DeleteLifecyclePolicy
          - ecr:DeleteRepositoryPolicy
          - ecr:PutImageScanningConfiguration
          - ecr:PutImageTagMutability
          - kms:DescribeKey
          - kms:CreateGrant
          - kms:RetireGrant
        """
        raise NotImplementedError
