from typing import List, Optional

from maps_adv.billing_proxy.lib.api.api_providers.schemas import (
    AccountManagerIdSchema,
    AgenciesSchema,
    ClientCreationInputSchema,
    ClientFindByUidSchema,
    ClientIdsSchema,
    ClientSchema,
    ClientSetAccountManagerSchema,
    ClientsSchema,
    ContractsSchema,
    UidsSchema,
)
from maps_adv.billing_proxy.lib.domain import ClientsDomain

from .base import with_schemas


class ClientsApiProvider:
    _domain: ClientsDomain

    def __init__(self, domain: ClientsDomain):
        self._domain = domain

    @with_schemas(output_schema=ClientSchema)
    async def retrieve_client(self, client_id: int):
        client_data = await self._domain.retrieve_client(client_id)

        return client_data

    @with_schemas(input_schema=AccountManagerIdSchema, output_schema=ClientsSchema)
    async def retrieve_clients_for_account(self, account_manager_id: int):
        return await self._domain.list_account_manager_clients(account_manager_id)

    @with_schemas(input_schema=ClientCreationInputSchema, output_schema=ClientSchema)
    async def register_client(
        self,
        uid: Optional[int],
        name: str,
        email: str,
        phone: str,
        domain: str,
        account_manager_id: int = None,
        has_accepted_offer: bool = False,
    ):
        return await self._domain.register_client(
            uid,
            name,
            email,
            phone,
            domain,
            account_manager_id,
            has_accepted_offer,
        )

    @with_schemas(input_schema=ClientCreationInputSchema, output_schema=ClientSchema)
    async def create_client(
        self,
        name: str,
        email: str,
        phone: str,
        domain: str,
        account_manager_id: int = None,
        has_accepted_offer: bool = False,
    ):
        return await self._domain.create_client(
            name, email, phone, domain, account_manager_id, has_accepted_offer
        )

    @with_schemas(input_schema=ClientSetAccountManagerSchema)
    async def set_account_manager_for_client(
        self, client_id: int, account_manager_id: int
    ):
        await self._domain.set_account_manager_for_client(client_id, account_manager_id)

    @with_schemas(input_schema=ClientFindByUidSchema, output_schema=ClientSchema)
    async def find_client_by_uid(self, uid: int):
        return await self._domain.find_client_by_uid(uid)

    @with_schemas(output_schema=AgenciesSchema)
    async def list_agencies(self):
        return await self._domain.list_agencies()

    @with_schemas(output_schema=ClientsSchema)
    async def list_agency_clients(self, agency_id: str):
        return await self._domain.list_agency_clients(int(agency_id))

    @with_schemas(output_schema=ClientsSchema)
    async def list_internal_clients(self):
        return await self._domain.list_internal_clients()

    @with_schemas(input_schema=ClientIdsSchema)
    async def add_clients_to_agency(self, client_ids: List[int], agency_id: str):
        await self._domain.add_clients_to_agency(client_ids, int(agency_id))

    @with_schemas(input_schema=ClientIdsSchema)
    async def add_clients_to_internal(self, client_ids: List[int]):
        await self._domain.add_clients_to_internal(client_ids)

    @with_schemas(input_schema=ClientIdsSchema)
    async def remove_clients_from_agency(self, client_ids: List[int], agency_id: str):
        await self._domain.remove_clients_from_agency(client_ids, int(agency_id))

    @with_schemas(input_schema=ClientIdsSchema)
    async def remove_clients_from_internal(self, client_ids: List[int]):
        await self._domain.remove_clients_from_internal(client_ids)

    @with_schemas(output_schema=ContractsSchema)
    async def list_client_contracts(self, client_id: int) -> List[dict]:
        return await self._domain.list_client_contracts(client_id)

    @with_schemas(output_schema=ContractsSchema)
    async def list_agency_contracts(self, agency_id: int) -> List[dict]:
        return await self._domain.list_agency_contracts(agency_id)

    async def set_client_has_accepted_offer(self, client_id: int, is_agency: bool):
        return await self._domain.set_client_has_accepted_offer(client_id, is_agency)

    @with_schemas(output_schema=ClientsSchema)
    async def list_clients(self):
        return await self._domain.list_clients()

    async def add_user_to_client(self, client_id: int, is_agency: bool, uid: int):
        return await self._domain.add_user_to_client(client_id, is_agency, uid)

    @with_schemas(output_schema=UidsSchema)
    async def list_client_representatives(self, client_id, is_agency: bool):
        return await self._domain.list_client_representatives(client_id, is_agency)
