from marshmallow import fields, pre_dump, validate

from maps_adv.billing_proxy.lib.domain import CurrencyType, PaymentType
from maps_adv.billing_proxy.proto import clients_pb2, common_pb2
from maps_adv.common.protomallow import PbDateField, PbEnumField, ProtobufSchema


class ClientSchema(ProtobufSchema):
    class Meta:
        pb_message_class = clients_pb2.Client

    id = fields.Integer()
    name = fields.String()
    email = fields.String()
    phone = fields.String()
    orders_count = fields.Integer(required=False)
    account_manager_id = fields.Integer(required=False)
    partner_agency_id = fields.Integer(required=False)
    has_accepted_offer = fields.Bool(required=False)


class ClientsSchema(ProtobufSchema):
    class Meta:
        pb_message_class = clients_pb2.Clients

    clients = fields.List(fields.Nested(ClientSchema))

    @pre_dump
    def to_dict(self, data):
        return {"clients": data}


class AgencySchema(ProtobufSchema):
    class Meta:
        pb_message_class = clients_pb2.Agency

    id = fields.Integer()
    name = fields.String()
    email = fields.String()
    phone = fields.String()
    has_accepted_offer = fields.Bool(required=False)


class AgenciesSchema(ProtobufSchema):
    class Meta:
        pb_message_class = clients_pb2.Agencies

    agencies = fields.List(fields.Nested(AgencySchema))

    @pre_dump
    def to_dict(self, data):
        return {"agencies": data}


class ClientCreationInputSchema(ProtobufSchema):
    class Meta:
        pb_message_class = clients_pb2.ClientCreationInput

    name = fields.String(validate=validate.Length(max=256))
    email = fields.String(validate=validate.Length(max=256))
    phone = fields.String(validate=validate.Length(max=64))
    account_manager_id = fields.Integer(required=False)
    domain = fields.String(validate=validate.Length(max=256))
    has_accepted_offer = fields.Bool(required=False)


class ClientSetAccountManagerSchema(ProtobufSchema):
    class Meta:
        pb_message_class = clients_pb2.ClientSetAccountManagerInput

    client_id = fields.Integer()
    account_manager_id = fields.Integer()


class ClientFindByUidSchema(ProtobufSchema):
    class Meta:
        pb_message_class = clients_pb2.ClientFindByUidSchema

    uid = fields.Integer()


class ClientIdsSchema(ProtobufSchema):
    class Meta:
        pb_message_class = clients_pb2.ClientIds

    client_ids = fields.List(fields.Integer())


class ContractSchema(ProtobufSchema):
    class Meta:
        pb_message_class = clients_pb2.Contract

    id = fields.Integer()
    external_id = fields.String()
    client_id = fields.Integer()
    currency = PbEnumField(
        enum=CurrencyType,
        pb_enum=common_pb2.CurrencyType,
        values_map=[
            (common_pb2.CurrencyType.Value("RUB"), CurrencyType.RUB),
            (common_pb2.CurrencyType.Value("BYN"), CurrencyType.BYN),
            (common_pb2.CurrencyType.Value("TRY"), CurrencyType.TRY),
            (common_pb2.CurrencyType.Value("KZT"), CurrencyType.KZT),
            (common_pb2.CurrencyType.Value("EUR"), CurrencyType.EUR),
            (common_pb2.CurrencyType.Value("USD"), CurrencyType.USD),
        ],
        by_value=True,
    )

    is_active = fields.Boolean()
    date_start = PbDateField()
    date_end = PbDateField(required=False)
    payment_type = PbEnumField(
        enum=PaymentType,
        pb_enum=common_pb2.PaymentType,
        values_map=[
            (common_pb2.PaymentType.Value("PRE_PAYMENT"), PaymentType.PRE),
            (common_pb2.PaymentType.Value("POST_PAYMENT"), PaymentType.POST),
        ],
        by_value=True,
    )
    preferred = fields.Boolean()


class ContractsSchema(ProtobufSchema):
    class Meta:
        pb_message_class = clients_pb2.Contracts

    contracts = fields.Nested(ContractSchema, many=True)

    @pre_dump
    def to_dict(self, data):
        return {"contracts": data}


class UidsSchema(ProtobufSchema):
    class Meta:
        pb_message_class = clients_pb2.Uids

    uids = fields.List(fields.Integer())

    @pre_dump
    def to_dict(self, data):
        return {"uids": data}
