from datetime import datetime
from enum import StrEnum
from typing import TypedDict

from localstack.aws.api import RequestContext, ServiceException, ServiceRequest, handler

Arn = str
AvailabilityErrorMessage = str
CertificateBody = str
CertificateChain = str
DomainNameString = str
IdempotencyToken = str
MaxItems = int
NextToken = str
NullableBoolean = bool
PcaArn = str
PositiveInteger = int
PrivateKey = str
ServiceErrorMessage = str
String = str
TagKey = str
TagValue = str
ValidationExceptionMessage = str


class CertificateExport(StrEnum):
    ENABLED = "ENABLED"
    DISABLED = "DISABLED"


class CertificateManagedBy(StrEnum):
    CLOUDFRONT = "CLOUDFRONT"


class CertificateStatus(StrEnum):
    PENDING_VALIDATION = "PENDING_VALIDATION"
    ISSUED = "ISSUED"
    INACTIVE = "INACTIVE"
    EXPIRED = "EXPIRED"
    VALIDATION_TIMED_OUT = "VALIDATION_TIMED_OUT"
    REVOKED = "REVOKED"
    FAILED = "FAILED"


class CertificateTransparencyLoggingPreference(StrEnum):
    ENABLED = "ENABLED"
    DISABLED = "DISABLED"


class CertificateType(StrEnum):
    IMPORTED = "IMPORTED"
    AMAZON_ISSUED = "AMAZON_ISSUED"
    PRIVATE = "PRIVATE"


class DomainStatus(StrEnum):
    PENDING_VALIDATION = "PENDING_VALIDATION"
    SUCCESS = "SUCCESS"
    FAILED = "FAILED"


class ExtendedKeyUsageName(StrEnum):
    TLS_WEB_SERVER_AUTHENTICATION = "TLS_WEB_SERVER_AUTHENTICATION"
    TLS_WEB_CLIENT_AUTHENTICATION = "TLS_WEB_CLIENT_AUTHENTICATION"
    CODE_SIGNING = "CODE_SIGNING"
    EMAIL_PROTECTION = "EMAIL_PROTECTION"
    TIME_STAMPING = "TIME_STAMPING"
    OCSP_SIGNING = "OCSP_SIGNING"
    IPSEC_END_SYSTEM = "IPSEC_END_SYSTEM"
    IPSEC_TUNNEL = "IPSEC_TUNNEL"
    IPSEC_USER = "IPSEC_USER"
    ANY = "ANY"
    NONE = "NONE"
    CUSTOM = "CUSTOM"


class FailureReason(StrEnum):
    NO_AVAILABLE_CONTACTS = "NO_AVAILABLE_CONTACTS"
    ADDITIONAL_VERIFICATION_REQUIRED = "ADDITIONAL_VERIFICATION_REQUIRED"
    DOMAIN_NOT_ALLOWED = "DOMAIN_NOT_ALLOWED"
    INVALID_PUBLIC_DOMAIN = "INVALID_PUBLIC_DOMAIN"
    DOMAIN_VALIDATION_DENIED = "DOMAIN_VALIDATION_DENIED"
    CAA_ERROR = "CAA_ERROR"
    PCA_LIMIT_EXCEEDED = "PCA_LIMIT_EXCEEDED"
    PCA_INVALID_ARN = "PCA_INVALID_ARN"
    PCA_INVALID_STATE = "PCA_INVALID_STATE"
    PCA_REQUEST_FAILED = "PCA_REQUEST_FAILED"
    PCA_NAME_CONSTRAINTS_VALIDATION = "PCA_NAME_CONSTRAINTS_VALIDATION"
    PCA_RESOURCE_NOT_FOUND = "PCA_RESOURCE_NOT_FOUND"
    PCA_INVALID_ARGS = "PCA_INVALID_ARGS"
    PCA_INVALID_DURATION = "PCA_INVALID_DURATION"
    PCA_ACCESS_DENIED = "PCA_ACCESS_DENIED"
    SLR_NOT_FOUND = "SLR_NOT_FOUND"
    OTHER = "OTHER"


class KeyAlgorithm(StrEnum):
    RSA_1024 = "RSA_1024"
    RSA_2048 = "RSA_2048"
    RSA_3072 = "RSA_3072"
    RSA_4096 = "RSA_4096"
    EC_prime256v1 = "EC_prime256v1"
    EC_secp384r1 = "EC_secp384r1"
    EC_secp521r1 = "EC_secp521r1"


class KeyUsageName(StrEnum):
    DIGITAL_SIGNATURE = "DIGITAL_SIGNATURE"
    NON_REPUDIATION = "NON_REPUDIATION"
    KEY_ENCIPHERMENT = "KEY_ENCIPHERMENT"
    DATA_ENCIPHERMENT = "DATA_ENCIPHERMENT"
    KEY_AGREEMENT = "KEY_AGREEMENT"
    CERTIFICATE_SIGNING = "CERTIFICATE_SIGNING"
    CRL_SIGNING = "CRL_SIGNING"
    ENCIPHER_ONLY = "ENCIPHER_ONLY"
    DECIPHER_ONLY = "DECIPHER_ONLY"
    ANY = "ANY"
    CUSTOM = "CUSTOM"


class RecordType(StrEnum):
    CNAME = "CNAME"


class RenewalEligibility(StrEnum):
    ELIGIBLE = "ELIGIBLE"
    INELIGIBLE = "INELIGIBLE"


class RenewalStatus(StrEnum):
    PENDING_AUTO_RENEWAL = "PENDING_AUTO_RENEWAL"
    PENDING_VALIDATION = "PENDING_VALIDATION"
    SUCCESS = "SUCCESS"
    FAILED = "FAILED"


class RevocationReason(StrEnum):
    UNSPECIFIED = "UNSPECIFIED"
    KEY_COMPROMISE = "KEY_COMPROMISE"
    CA_COMPROMISE = "CA_COMPROMISE"
    AFFILIATION_CHANGED = "AFFILIATION_CHANGED"
    SUPERCEDED = "SUPERCEDED"
    SUPERSEDED = "SUPERSEDED"
    CESSATION_OF_OPERATION = "CESSATION_OF_OPERATION"
    CERTIFICATE_HOLD = "CERTIFICATE_HOLD"
    REMOVE_FROM_CRL = "REMOVE_FROM_CRL"
    PRIVILEGE_WITHDRAWN = "PRIVILEGE_WITHDRAWN"
    A_A_COMPROMISE = "A_A_COMPROMISE"


class SortBy(StrEnum):
    CREATED_AT = "CREATED_AT"


class SortOrder(StrEnum):
    ASCENDING = "ASCENDING"
    DESCENDING = "DESCENDING"


class ValidationMethod(StrEnum):
    EMAIL = "EMAIL"
    DNS = "DNS"
    HTTP = "HTTP"


class AccessDeniedException(ServiceException):
    code: str = "AccessDeniedException"
    sender_fault: bool = False
    status_code: int = 400


class ConflictException(ServiceException):
    code: str = "ConflictException"
    sender_fault: bool = False
    status_code: int = 400


class InvalidArgsException(ServiceException):
    code: str = "InvalidArgsException"
    sender_fault: bool = False
    status_code: int = 400


class InvalidArnException(ServiceException):
    code: str = "InvalidArnException"
    sender_fault: bool = False
    status_code: int = 400


class InvalidDomainValidationOptionsException(ServiceException):
    code: str = "InvalidDomainValidationOptionsException"
    sender_fault: bool = False
    status_code: int = 400


class InvalidParameterException(ServiceException):
    code: str = "InvalidParameterException"
    sender_fault: bool = False
    status_code: int = 400


class InvalidStateException(ServiceException):
    code: str = "InvalidStateException"
    sender_fault: bool = False
    status_code: int = 400


class InvalidTagException(ServiceException):
    code: str = "InvalidTagException"
    sender_fault: bool = False
    status_code: int = 400


class LimitExceededException(ServiceException):
    code: str = "LimitExceededException"
    sender_fault: bool = False
    status_code: int = 400


class RequestInProgressException(ServiceException):
    code: str = "RequestInProgressException"
    sender_fault: bool = False
    status_code: int = 400


class ResourceInUseException(ServiceException):
    code: str = "ResourceInUseException"
    sender_fault: bool = False
    status_code: int = 400


class ResourceNotFoundException(ServiceException):
    code: str = "ResourceNotFoundException"
    sender_fault: bool = False
    status_code: int = 400


class TagPolicyException(ServiceException):
    code: str = "TagPolicyException"
    sender_fault: bool = False
    status_code: int = 400


class ThrottlingException(ServiceException):
    code: str = "ThrottlingException"
    sender_fault: bool = False
    status_code: int = 400


class TooManyTagsException(ServiceException):
    code: str = "TooManyTagsException"
    sender_fault: bool = False
    status_code: int = 400


class ValidationException(ServiceException):
    code: str = "ValidationException"
    sender_fault: bool = False
    status_code: int = 400


class Tag(TypedDict, total=False):
    Key: TagKey
    Value: TagValue | None


TagList = list[Tag]


class AddTagsToCertificateRequest(ServiceRequest):
    CertificateArn: Arn
    Tags: TagList


CertificateBodyBlob = bytes
CertificateChainBlob = bytes


class CertificateOptions(TypedDict, total=False):
    CertificateTransparencyLoggingPreference: CertificateTransparencyLoggingPreference | None
    Export: CertificateExport | None


class ExtendedKeyUsage(TypedDict, total=False):
    Name: ExtendedKeyUsageName | None
    OID: String | None


ExtendedKeyUsageList = list[ExtendedKeyUsage]


class KeyUsage(TypedDict, total=False):
    Name: KeyUsageName | None


KeyUsageList = list[KeyUsage]
TStamp = datetime


class HttpRedirect(TypedDict, total=False):
    RedirectFrom: String | None
    RedirectTo: String | None


class ResourceRecord(TypedDict, total=False):
    Name: String
    Type: RecordType
    Value: String


ValidationEmailList = list[String]


class DomainValidation(TypedDict, total=False):
    DomainName: DomainNameString
    ValidationEmails: ValidationEmailList | None
    ValidationDomain: DomainNameString | None
    ValidationStatus: DomainStatus | None
    ResourceRecord: ResourceRecord | None
    HttpRedirect: HttpRedirect | None
    ValidationMethod: ValidationMethod | None


DomainValidationList = list[DomainValidation]


class RenewalSummary(TypedDict, total=False):
    RenewalStatus: RenewalStatus
    DomainValidationOptions: DomainValidationList
    RenewalStatusReason: FailureReason | None
    UpdatedAt: TStamp


InUseList = list[String]
DomainList = list[DomainNameString]


class CertificateDetail(TypedDict, total=False):
    CertificateArn: Arn | None
    DomainName: DomainNameString | None
    SubjectAlternativeNames: DomainList | None
    ManagedBy: CertificateManagedBy | None
    DomainValidationOptions: DomainValidationList | None
    Serial: String | None
    Subject: String | None
    Issuer: String | None
    CreatedAt: TStamp | None
    IssuedAt: TStamp | None
    ImportedAt: TStamp | None
    Status: CertificateStatus | None
    RevokedAt: TStamp | None
    RevocationReason: RevocationReason | None
    NotBefore: TStamp | None
    NotAfter: TStamp | None
    KeyAlgorithm: KeyAlgorithm | None
    SignatureAlgorithm: String | None
    InUseBy: InUseList | None
    FailureReason: FailureReason | None
    Type: CertificateType | None
    RenewalSummary: RenewalSummary | None
    KeyUsages: KeyUsageList | None
    ExtendedKeyUsages: ExtendedKeyUsageList | None
    CertificateAuthorityArn: Arn | None
    RenewalEligibility: RenewalEligibility | None
    Options: CertificateOptions | None


CertificateStatuses = list[CertificateStatus]
ExtendedKeyUsageNames = list[ExtendedKeyUsageName]
KeyUsageNames = list[KeyUsageName]


class CertificateSummary(TypedDict, total=False):
    CertificateArn: Arn | None
    DomainName: DomainNameString | None
    SubjectAlternativeNameSummaries: DomainList | None
    HasAdditionalSubjectAlternativeNames: NullableBoolean | None
    Status: CertificateStatus | None
    Type: CertificateType | None
    KeyAlgorithm: KeyAlgorithm | None
    KeyUsages: KeyUsageNames | None
    ExtendedKeyUsages: ExtendedKeyUsageNames | None
    ExportOption: CertificateExport | None
    InUse: NullableBoolean | None
    Exported: NullableBoolean | None
    RenewalEligibility: RenewalEligibility | None
    NotBefore: TStamp | None
    NotAfter: TStamp | None
    CreatedAt: TStamp | None
    IssuedAt: TStamp | None
    ImportedAt: TStamp | None
    RevokedAt: TStamp | None
    ManagedBy: CertificateManagedBy | None


CertificateSummaryList = list[CertificateSummary]


class DeleteCertificateRequest(ServiceRequest):
    CertificateArn: Arn


class DescribeCertificateRequest(ServiceRequest):
    CertificateArn: Arn


class DescribeCertificateResponse(TypedDict, total=False):
    Certificate: CertificateDetail | None


class DomainValidationOption(TypedDict, total=False):
    DomainName: DomainNameString
    ValidationDomain: DomainNameString


DomainValidationOptionList = list[DomainValidationOption]


class ExpiryEventsConfiguration(TypedDict, total=False):
    DaysBeforeExpiry: PositiveInteger | None


PassphraseBlob = bytes


class ExportCertificateRequest(ServiceRequest):
    CertificateArn: Arn
    Passphrase: PassphraseBlob


class ExportCertificateResponse(TypedDict, total=False):
    Certificate: CertificateBody | None
    CertificateChain: CertificateChain | None
    PrivateKey: PrivateKey | None


ExtendedKeyUsageFilterList = list[ExtendedKeyUsageName]
KeyAlgorithmList = list[KeyAlgorithm]
KeyUsageFilterList = list[KeyUsageName]


class Filters(TypedDict, total=False):
    extendedKeyUsage: ExtendedKeyUsageFilterList | None
    keyUsage: KeyUsageFilterList | None
    keyTypes: KeyAlgorithmList | None
    exportOption: CertificateExport | None
    managedBy: CertificateManagedBy | None


class GetAccountConfigurationResponse(TypedDict, total=False):
    ExpiryEvents: ExpiryEventsConfiguration | None


class GetCertificateRequest(ServiceRequest):
    CertificateArn: Arn


class GetCertificateResponse(TypedDict, total=False):
    Certificate: CertificateBody | None
    CertificateChain: CertificateChain | None


PrivateKeyBlob = bytes


class ImportCertificateRequest(ServiceRequest):
    CertificateArn: Arn | None
    Certificate: CertificateBodyBlob
    PrivateKey: PrivateKeyBlob
    CertificateChain: CertificateChainBlob | None
    Tags: TagList | None


class ImportCertificateResponse(TypedDict, total=False):
    CertificateArn: Arn | None


class ListCertificatesRequest(ServiceRequest):
    CertificateStatuses: CertificateStatuses | None
    Includes: Filters | None
    NextToken: NextToken | None
    MaxItems: MaxItems | None
    SortBy: SortBy | None
    SortOrder: SortOrder | None


class ListCertificatesResponse(TypedDict, total=False):
    NextToken: NextToken | None
    CertificateSummaryList: CertificateSummaryList | None


class ListTagsForCertificateRequest(ServiceRequest):
    CertificateArn: Arn


class ListTagsForCertificateResponse(TypedDict, total=False):
    Tags: TagList | None


class PutAccountConfigurationRequest(ServiceRequest):
    ExpiryEvents: ExpiryEventsConfiguration | None
    IdempotencyToken: IdempotencyToken


class RemoveTagsFromCertificateRequest(ServiceRequest):
    CertificateArn: Arn
    Tags: TagList


class RenewCertificateRequest(ServiceRequest):
    CertificateArn: Arn


class RequestCertificateRequest(ServiceRequest):
    DomainName: DomainNameString
    ValidationMethod: ValidationMethod | None
    SubjectAlternativeNames: DomainList | None
    IdempotencyToken: IdempotencyToken | None
    DomainValidationOptions: DomainValidationOptionList | None
    Options: CertificateOptions | None
    CertificateAuthorityArn: PcaArn | None
    Tags: TagList | None
    KeyAlgorithm: KeyAlgorithm | None
    ManagedBy: CertificateManagedBy | None


class RequestCertificateResponse(TypedDict, total=False):
    CertificateArn: Arn | None


class ResendValidationEmailRequest(ServiceRequest):
    CertificateArn: Arn
    Domain: DomainNameString
    ValidationDomain: DomainNameString


class RevokeCertificateRequest(ServiceRequest):
    CertificateArn: Arn
    RevocationReason: RevocationReason


class RevokeCertificateResponse(TypedDict, total=False):
    CertificateArn: Arn | None


class UpdateCertificateOptionsRequest(ServiceRequest):
    CertificateArn: Arn
    Options: CertificateOptions


class AcmApi:
    service: str = "acm"
    version: str = "2015-12-08"

    @handler("AddTagsToCertificate")
    def add_tags_to_certificate(
        self, context: RequestContext, certificate_arn: Arn, tags: TagList, **kwargs
    ) -> None:
        raise NotImplementedError

    @handler("DeleteCertificate")
    def delete_certificate(self, context: RequestContext, certificate_arn: Arn, **kwargs) -> None:
        raise NotImplementedError

    @handler("DescribeCertificate")
    def describe_certificate(
        self, context: RequestContext, certificate_arn: Arn, **kwargs
    ) -> DescribeCertificateResponse:
        raise NotImplementedError

    @handler("ExportCertificate")
    def export_certificate(
        self, context: RequestContext, certificate_arn: Arn, passphrase: PassphraseBlob, **kwargs
    ) -> ExportCertificateResponse:
        raise NotImplementedError

    @handler("GetAccountConfiguration")
    def get_account_configuration(
        self, context: RequestContext, **kwargs
    ) -> GetAccountConfigurationResponse:
        raise NotImplementedError

    @handler("GetCertificate")
    def get_certificate(
        self, context: RequestContext, certificate_arn: Arn, **kwargs
    ) -> GetCertificateResponse:
        raise NotImplementedError

    @handler("ImportCertificate")
    def import_certificate(
        self,
        context: RequestContext,
        certificate: CertificateBodyBlob,
        private_key: PrivateKeyBlob,
        certificate_arn: Arn | None = None,
        certificate_chain: CertificateChainBlob | None = None,
        tags: TagList | None = None,
        **kwargs,
    ) -> ImportCertificateResponse:
        raise NotImplementedError

    @handler("ListCertificates")
    def list_certificates(
        self,
        context: RequestContext,
        certificate_statuses: CertificateStatuses | None = None,
        includes: Filters | None = None,
        next_token: NextToken | None = None,
        max_items: MaxItems | None = None,
        sort_by: SortBy | None = None,
        sort_order: SortOrder | None = None,
        **kwargs,
    ) -> ListCertificatesResponse:
        raise NotImplementedError

    @handler("ListTagsForCertificate")
    def list_tags_for_certificate(
        self, context: RequestContext, certificate_arn: Arn, **kwargs
    ) -> ListTagsForCertificateResponse:
        raise NotImplementedError

    @handler("PutAccountConfiguration")
    def put_account_configuration(
        self,
        context: RequestContext,
        idempotency_token: IdempotencyToken,
        expiry_events: ExpiryEventsConfiguration | None = None,
        **kwargs,
    ) -> None:
        raise NotImplementedError

    @handler("RemoveTagsFromCertificate")
    def remove_tags_from_certificate(
        self, context: RequestContext, certificate_arn: Arn, tags: TagList, **kwargs
    ) -> None:
        raise NotImplementedError

    @handler("RenewCertificate")
    def renew_certificate(self, context: RequestContext, certificate_arn: Arn, **kwargs) -> None:
        raise NotImplementedError

    @handler("RequestCertificate")
    def request_certificate(
        self,
        context: RequestContext,
        domain_name: DomainNameString,
        validation_method: ValidationMethod | None = None,
        subject_alternative_names: DomainList | None = None,
        idempotency_token: IdempotencyToken | None = None,
        domain_validation_options: DomainValidationOptionList | None = None,
        options: CertificateOptions | None = None,
        certificate_authority_arn: PcaArn | None = None,
        tags: TagList | None = None,
        key_algorithm: KeyAlgorithm | None = None,
        managed_by: CertificateManagedBy | None = None,
        **kwargs,
    ) -> RequestCertificateResponse:
        raise NotImplementedError

    @handler("ResendValidationEmail")
    def resend_validation_email(
        self,
        context: RequestContext,
        certificate_arn: Arn,
        domain: DomainNameString,
        validation_domain: DomainNameString,
        **kwargs,
    ) -> None:
        raise NotImplementedError

    @handler("RevokeCertificate")
    def revoke_certificate(
        self,
        context: RequestContext,
        certificate_arn: Arn,
        revocation_reason: RevocationReason,
        **kwargs,
    ) -> RevokeCertificateResponse:
        raise NotImplementedError

    @handler("UpdateCertificateOptions")
    def update_certificate_options(
        self, context: RequestContext, certificate_arn: Arn, options: CertificateOptions, **kwargs
    ) -> None:
        raise NotImplementedError
