# -*- coding: utf-8 -*-
from collections import namedtuple

from datacloud.score_api.storage.ydb.ydb_tables.config_tables.score_path_table import ScorePathTable
from datacloud.score_api.storage.ydb.ydb_tables.config_tables.partner_scores_table import PartnerScoresTable

from datacloud.score_api.storage.cache.ttl_cache import TtlCache


__all__ = [
    'YdbScorePathStorage'
]


YdbScorePathCacheValue = namedtuple('YdbScorePathCacheValue', 'score_path internal_score_name')


class YdbScorePathStorage:
    def __init__(self, ydb_manager, database, partner_score_table_path, score_path_table_path):
        self._ydb_manager = ydb_manager
        self._database = database

        self._score_path_table_path = score_path_table_path
        self._partner_scores_table_path = partner_score_table_path

        self._partner_scores_table = None
        self._score_path_table = None

        self._score_path_cache = TtlCache(120)
        self._partner_scores_cache = TtlCache(130)

    @property
    def score_path_table(self):
        if self._score_path_table is None:
            self._score_path_table = ScorePathTable(self._ydb_manager, self._database, self._score_path_table_path)
        return self._score_path_table

    @property
    def partner_scores_table(self):
        if self._partner_scores_table is None:
            self._partner_scores_table = PartnerScoresTable(self._ydb_manager, self._database, self._partner_scores_table_path)
        return self._partner_scores_table

    def get_score_path_with_cache(self, partner_id, partner_score_name):
        cache_key = (partner_id, partner_score_name)
        status, val = self._score_path_cache.get(cache_key)
        if status == TtlCache.Status.OK:
            return val

        partner_score_record = self.partner_scores_table.get_one(PartnerScoresTable.Record(partner_id, partner_score_name))
        if not partner_score_record:
            return None
        score_path_record = self.score_path_table.get_one(ScorePathTable.Record(partner_score_record.internal_score_name))
        if not score_path_record:
            return None

        val = YdbScorePathCacheValue(score_path_record.score_path, partner_score_record.internal_score_name)
        self._score_path_cache.insert(cache_key, val)

        return val

    def get_score_path(self, partner_id, partner_score_name):
        cache = self.get_score_path_with_cache(partner_id, partner_score_name)
        if cache is None:
            return None
        return cache.score_path

    def get_internal_score_name(self, partner_id, partner_score_name):
        cache = self.get_score_path_with_cache(partner_id, partner_score_name)
        if cache is None:
            return None
        return cache.internal_score_name

    # Получить список скоров доступных пользователю
    def get_user_scores(self, partner_id):
        print('[WARNING] DONT USE get_user_scores, USER get_partner_scores instead')
        return self.get_partner_scores(partner_id)

    def get_partner_scores(self, partner_id):
        """
        Returs list of user scores
        """
        status, val = self._partner_scores_cache.get(partner_id)
        if status == TtlCache.Status.OK:
            return val
        partner_scores = self.partner_scores_table.get_available_partner_scores(partner_id)
        if not partner_scores:
            return []
        partner_scores = tuple(partner_scores)
        self._partner_scores_cache.insert(partner_id, partner_scores)
        return partner_scores
