import json

from marshmallow import ValidationError, fields, post_load, pre_dump

from maps_adv.adv_store.api.proto.campaign_pb2 import (
    CampaignExport,
    CampaignExportList,
    Platform,
    PublicationEnv,
)
from maps_adv.adv_store.api.schemas.enums import (
    PlatformEnum,
    PublicationEnvEnum,
)
from maps_adv.common.helpers.enums import CampaignTypeEnum
from maps_adv.common.proto.campaign_pb2 import CampaignType
from maps_adv.common.protomallow import PbEnumField, ProtobufSchema, PbDateTimeField

from .actions import ActionSchema
from .campaigns import SettingsSchema
from .creatives import CreativeSchema
from .enums_map import ENUMS_MAP
from .placing import PlacingSchema


class CampaignExportSchema(ProtobufSchema):
    class Meta:
        pb_message_class = CampaignExport

    id = fields.Integer()
    publication_envs = fields.List(
        PbEnumField(
            enum=PublicationEnvEnum,
            pb_enum=PublicationEnv.Enum,
            values_map=ENUMS_MAP["publication_env"],
        )
    )
    campaign_type = PbEnumField(
        enum=CampaignTypeEnum,
        pb_enum=CampaignType.Enum,
        values_map=ENUMS_MAP["campaign_type"],
    )
    placing = fields.Nested(PlacingSchema)
    platforms = fields.List(
        PbEnumField(
            enum=PlatformEnum,
            pb_enum=Platform.Enum,
            values_map=ENUMS_MAP["platforms"],
        )
    )
    creatives = fields.Nested(CreativeSchema, many=True)
    actions = fields.Nested(ActionSchema, many=True)

    order_id = fields.Integer(required=False)
    user_display_limit = fields.Integer(required=False)
    user_daily_display_limit = fields.Integer(required=False)
    targeting = fields.String(required=False)
    display_probability = fields.String(required=False)
    display_chance = fields.Integer(required=False)
    settings = fields.Nested(SettingsSchema)
    total_daily_display_limit = fields.Integer(required=False, missing=None)
    total_daily_action_limit = fields.Integer(required=False, missing=None)
    total_display_minutes_today = fields.Integer(required=False, missing=None)
    total_display_minutes_left_today = fields.Integer(required=False, missing=None)
    timezone = fields.String()
    cost = fields.Float(required=False)
    paid_till = PbDateTimeField(required=False)

    @post_load
    def targeting_load(self, data):
        try:
            data["targeting"] = json.loads(data.get("targeting", "{}"))
        except json.JSONDecodeError:
            raise ValidationError("Invalid targeting field")

    @pre_dump
    def targeting_dump(self, data):
        data["targeting"] = json.dumps(data["targeting"])


class CampaignForExportListSchema(ProtobufSchema):
    class Meta:
        pb_message_class = CampaignExportList

    campaigns = fields.Nested(CampaignExportSchema, many=True)
