"""
This type stub file was generated by pyright.
"""
import os
from types import TracebackType
from typing import Any, Callable, Dict, List, Optional, Protocol, Type, TypedDict, TypeVar, Union, overload

from pactman.mock.consumer import Consumer
from pactman.mock.matchers import Matcher
from pactman.mock.provider import Provider

"""API for creating a contract and configuring the mock service."""
USE_MOCKING_SERVER = os.environ.get("PACT_USE_MOCKING_SERVER", "no") == "yes"

class VersionInfoLike(Protocol):
    """This is a minimal type stub for semver.Version."""

    major: int
    minor: int
    patch: int
    prerelease: Optional[Union[str, int]]
    build: Optional[Union[str, int]]

def ensure_pact_dir(pact_dir: str) -> None: ...

class ProviderState(TypedDict):
    name: str
    params: Dict[str, str]

class Request(TypedDict):
    method: str
    path: str

class V2Interaction(TypedDict):
    providerState: str
    request: Request

class V3Interaction(TypedDict):
    providerStates: List[ProviderState]
    request: Request

Interaction = Union[V2Interaction, V3Interaction]

class Pacticipant(TypedDict):
    name: str

class PactStructMetaSpecification(TypedDict):
    version: str

class PactStructMeta(TypedDict):
    pactSpecification: PactStructMetaSpecification

class PactStruct(TypedDict):
    consumer: Pacticipant
    provider: Pacticipant
    interactions: List[Interaction]
    metadata: PactStructMeta

P = TypeVar('P', bound=Pact)

class Pact(object):
    """
    Represents a contract between a consumer and provider.

    Provides Python context handlers to configure the Pact mock service to
    perform tests on a Python consumer. For example:

    >>> from pactman import Consumer, Provider
    >>> pact = Consumer('consumer').has_pact_with(Provider('provider'))
    >>> (pact.given('the echo service is available')
    ...  .upon_receiving('a request is made to the echo service')
    ...  .with_request('get', '/echo', query={'text': 'Hello!'})
    ...  .will_respond_with(200, body='Hello!'))
    >>> with pact:
    ...   requests.get(pact.uri + '/echo?text=Hello!')

    The GET request is made to the mock service, which will verify that it
    was a GET to /echo with a query string with a key named `text` and its
    value is `Hello!`. If the request does not match an error is raised, if it
    does match the defined interaction, it will respond with the text `Hello!`.
    """

    HEADERS: Dict[str, str] = ...

    scheme: str
    file_write_mode: str
    host_name: str
    log_dir: str
    pact_dir: str
    port: int
    provider: Provider
    ssl: bool
    sslcert: str
    sslkey: str
    version: str
    semver: VersionInfoLike
    use_mocking_server: bool
    _interactions: List[Interaction]

    _pact_dir_checked: bool
    _enter_count: int

    # it's not actually a property, but it's the only way
    # to parameterize the generic with the type of P
    @property
    def consumer(self: P) -> Consumer[P]: ...
    def __init__(
        self: P,
        consumer: Consumer[P],
        provider: Provider,
        host_name: str = ...,
        port: int = ...,
        log_dir: str = ...,
        ssl: bool = ...,
        sslcert: Optional[str] = ...,
        sslkey: Optional[str] = ...,
        pact_dir: str = ...,
        version: str = ...,
        file_write_mode: str = ...,
        use_mocking_server: bool = ...,
    ) -> None:
        """
        Constructor for Pact.

        :param consumer: The consumer for this contract.
        :type consumer: pact.Consumer
        :param provider: The provider for this contract.
        :type provider: pact.Provider
        :param host_name: The host name where the mock service is running.
        :type host_name: str
        :param port: The port number where the mock service is running. Defaults
            to a port >= 8050.
        :type port: int
        :param log_dir: The directory where logs should be written. Defaults to
            the current directory.
        :type log_dir: str
        :param ssl: Flag to control the use of a self-signed SSL cert to run
            the server over HTTPS , defaults to False.
        :type ssl: bool
        :param sslcert: Path to a custom self-signed SSL cert file, 'ssl'
            option must be set to True to use this option. Defaults to None.
        :type sslcert: str
        :param sslkey: Path to a custom key and self-signed SSL cert key file,
            'ssl' option must be set to True to use this option.
            Defaults to None.
        :type sslkey: str
        :param pact_dir: Directory where the resulting pact files will be
            written. Defaults to the current directory.
        :type pact_dir: str
        :param version: The Pact Specification version to use, defaults to
            '2.0.0'.
        :type version: str
        :param file_write_mode: `overwrite` or `merge`. Use `merge` when
            running multiple mock service instances in parallel for the same
            consumer/provider pair. Ensure the pact file is deleted before
            running tests when using this option so that interactions deleted
            from the code are not maintained in the file. Defaults to
            `overwrite`.
        :type file_write_mode: str
        :param use_mocking_server: If True the mocking will be done using a
            HTTP server rather than patching urllib3 connections.
        :type use_mocking_server: bool
        """
        ...
    @property
    def uri(self) -> str: ...
    BASE_PORT_NUMBER: int = ...
    @classmethod
    def allocate_port(cls) -> int: ...
    def check_existing_file(self) -> None: ...
    @property
    def pact_json_filename(self) -> str: ...
    @overload
    def given(self: P, provider_state: None) -> P: ...
    @overload
    def given(self: P, provider_state: str, **params: str) -> P: ...
    @overload
    def given(self: P, provider_state: List[ProviderState]) -> P:
        """
        Define the provider state for this pact.

        When the provider verifies this contract, they will use this field to
        setup pre-defined data that will satisfy the response expectations.

        In pact v2 the provider state is a short sentence that is unique to describe
        the provider state for this contract. For example:

            "an alligator with the given name Mary exists and the spam nozzle is operating"

        In pact v3 the provider state is a list of state specifications with a name and
        associated params to define specific values for the state. This may be provided
        in two ways. Either call with a single list, for example:

            [
                {
                    "name": "an alligator with the given name exists",
                    "params": {"name" : "Mary"}
                }, {
                    "name": "the spam nozzle is operating",
                    "params" : {}
                }
            ]

        or for convenience call `.given()` with a string as in v2, which implies a single
        provider state, with params taken from keyword arguments like so:

            .given("an alligator with the given name exists", name="Mary")

        If additional provider states are required for a v3 pact you may either use the list
        form above, or make an additional call to `.and_given()`.

        If you don't have control over the provider, and they cannot implement a provider
        state, you may use an explicit `None` for the provider state value. This is
        discouraged as it introduces fragile external dependencies in your tests.

        :param provider_state: The state as described above.
        :type provider_state: string or list as above
        :rtype: Pact
        """
        ...
    def and_given(self: P, provider_state: str, **params: str) -> P:
        """
        Define an additional provider state for this pact.

        Supply the provider state name and any params taken in keyword arguments like so:

            .given("an alligator with the given name exists", name="Mary")

        :param provider_state: The state as described above.
        :type provider_state: string or list as above
        :rtype: Pact
        """
        ...
    def setup(self) -> None: ...
    def start_mocking(self) -> None: ...
    def stop_mocking(self) -> None: ...
    start_service: Callable[[Pact], None] = ...
    stop_service: Callable[[Pact], None] = ...
    def upon_receiving(self: P, scenario: str) -> P:
        """
        Define the name of this contract.

        :param scenario: A unique name for this contract.
        :type scenario: basestring
        :rtype: Pact
        """
        ...
    def verify(self) -> None:
        """
        Have the mock service verify all interactions occurred.

        Calls the mock service to verify that all interactions occurred as
        expected, and has it write out the contracts to disk.

        :raises AssertionError: When not all interactions are found.
        """
        ...
    def with_request(
        self: P,
        method: str,
        path: Union[str, Matcher],
        body: Optional[Union[List[Any], Dict[str, Any]]] = ...,
        headers: Optional[Dict[str, str]] = ...,
        query: Optional[Union[str, Dict[str, str]]] = ...,
    ) -> P:
        """
        Define the request the request that the client is expected to perform.

        :param method: The HTTP method.
        :type method: str
        :param path: The path portion of the URI the client will access.
        :type path: str, Matcher
        :param body: The request body, can be a string or an object that will
            serialize to JSON, like list or dict, defaults to None.
        :type body: list, dict or None
        :param headers: The headers the client is expected to include on with
            this request. Defaults to None.
        :type headers: dict or None
        :param query: The query options the client is expected to send. Can be
            a dict of keys and values, or a URL encoded string.
            Defaults to None.
        :type query: dict, str, or None
        :rtype: Pact
        """
        ...
    def will_respond_with(
        self: P,
        status: int,
        headers: Optional[Dict[str, str]] = ...,
        body: Optional[Union[Matcher, str, Dict[str, Any], List[Any]]] = ...,
    ) -> P:
        """
        Define the response the server is expected to create.

        :param status: The HTTP status code.
        :type status: int
        :param headers: All required headers. Defaults to None.
        :type headers: dict or None
        :param body: The response body, or a collection of Matcher objects to
            allow for pattern matching. Defaults to None.
        :type body: Matcher, dict, list, basestring, or None
        :rtype: Pact
        """
        ...
    _auto_mocked: bool = ...
    def __enter__(self) -> None:
        """
        Handler for entering a Python context.

        Sets up the mock service to expect the client requests.
        """
        ...
    def __exit__(self, exc_type: Type[Exception], exc_val: Exception, exc_tb: TracebackType) -> None:
        """
        Handler for exiting a Python context.

        Calls the mock service to verify that all interactions occurred as
        expected, and has it write out the contracts to disk.
        """
        ...
    def construct_pact(self, interaction: Interaction) -> PactStruct:
        """Construct a pact JSON data structure for the interaction.
        """
        ...
