# -*- coding: utf-8 -*-
import logging
import numpy as np
from ydb_score import ScoreValueView
from datacloud.dev_utils.geo.geo_features import get_features, sigmoid
from datacloud.dev_utils.geo.addrs_resolve import AddrsResolver


logger = logging.getLogger(__name__)


__all__ = [
    'GeoScoreValueView',
]

REQUEST_LOG_TAG = 'geo_score_value_request'
input_schema = {
    "description": "DataCloud score API query",
    "id": "score_request",
    "properties": {
        "response_ids": {
          "type": "object",
          "properties": {
              "external_id": {
                  "type": "string"
              },
              "request_id": {
                  "type": "string"
              }
          }
        },
        "user_ids": {
            "type": "object",
            "properties": {
                "external_id": {
                    "type": "string"
                },
                "phones": {
                    "type": "array",
                    "items": {
                        "type": "object",
                        "properties": {
                            "id_value": {
                                "type": "string"
                            },
                            "phone": {
                                "type": "string"
                            }
                        }
                    }
                },
                "emails": {
                    "type": "array",
                    "items": {
                        "type": "object",
                        "properties": {
                            "id_value": {
                                "type": "string"
                            },
                            "email": {
                                "type": "string"
                            }
                        }
                    }
                },
                "cookies": {
                    "type": "array",
                    "items": {
                        "type": "object",
                        "properties": {
                            "cookie": {
                                "type": "string"
                            },
                            "cookie_vendor": {
                                "type": "string"
                            }
                        },
                        "required": [
                            "cookie",
                            "cookie_vendor"
                        ]
                    }
                },
                "addresses": {
                    "type": "object",
                    "properties": {
                        "home": {
                            "type": "string"
                        },
                        "reg": {
                            "type": "string"
                        },
                        "work": {
                            "type": "string"
                        }
                    }
                }
            }
        },
        "scores": {
            "type": "array",
            "items": {
                "type": "object",
                "properties": {
                    "score_name": {
                        "type": "string"
                    }
                },
                "required": ["score_name"]
            }
        }
    },
    "required": [
        "user_ids",
        "scores"
    ]
}


output_schema = {
    "description": "DataCloud score API response",
    "id": "score_response",
    "properties": {
        "response_ids": {
          "type": "object",
          "properties": {
              "external_id": {
                  "type": "string"
              },
              "request_id": {
                  "type": "string"
              }
          }
        },
        "scores": {
            "type": "array",
            "items": {
                "type": "object",
                "properties": {
                    "score_name": {
                        "type": "string",
                    },
                    "has_score": {
                        "type": "boolean",
                    },
                    "score_value": {
                        "type": "number",
                    }
                },
                "required": ["score_name", "has_score"]
            }
        }
    },
    "required": ["scores"]
}


class GeoScoreValueView(ScoreValueView):
    """
    View for reading score values with geo features
    """
    request_body_schema = input_schema
    request_body_required = True
    result_schema = output_schema
    permissions = {'partner_read'}

    def __init__(self, ydb_manager, connection_params, ydb_root_dir, score_path_storage, geo_storage, cookie_sync_api, *args, **kwargs):
        super(GeoScoreValueView, self).__init__(ydb_manager, connection_params, ydb_root_dir, score_path_storage, cookie_sync_api, *args, **kwargs)
        self.geo_storage = geo_storage
        self.addresses_resolver = AddrsResolver()

    def get_addresses(self, user_ids):
        addresses = user_ids.get('addresses', {})

        home = self.addresses_resolver.resolve_addr_or_none(addresses.get('home', ''))
        reg = self.addresses_resolver.resolve_addr_or_none(addresses.get('reg', ''))
        work = self.addresses_resolver.resolve_addr_or_none(addresses.get('work', ''))

        return home, reg, work

    def _get_score_values(self, partner_id, query):
        linear_parts = super(GeoScoreValueView, self)._get_score_values(partner_id, query)
        if all(linear_part.value is None for linear_part in linear_parts):
            return linear_parts

        user_ids = query.get('user_ids')
        user_info = []
        user_info.extend(user_ids.get('phones', []))
        user_info.extend(user_ids.get('emails', []))
        hashed_id_values = set()
        hashed_id_values = hashed_id_values.union([cid for cid in self._ScoreStorageClass.convert_id_values_to_hashed_id_values(user_info)])

        home, reg, work = self.get_addresses(user_ids)

        result = []
        for linear_part in linear_parts:
            if linear_part.value is not None:
                partner_score_name = linear_part.name
                internal_score_name = self._score_path_storage.get_internal_score_name(partner_id, partner_score_name)

                points = self.geo_storage.get_geo_logs_by_id_values(internal_score_name, hashed_id_values)
                weights = self.geo_storage.get_geo_weights(internal_score_name)

                geo_features = get_features((home, reg, work), points)
                geo_part = np.dot(geo_features, weights)

                score = sigmoid(linear_part.value + geo_part)
                result.append(linear_part._replace(value=score))
            else:
                result.append(linear_part)

        return result
