from typing import Callable
import logging
from datetime import date, timedelta

from algo.data.cache.dynamo import DynamoCache
from algo.data.common import PriceStream, Symbol
from algo.util import get_week_start_day

from .dynamo import DynamoCache

CachableDataSource = Callable[[str, Symbol], PriceStream]

log = logging.getLogger(__name__)

dynamo_cache = DynamoCache()


def get_cached_week_data_stream(symbol: Symbol, week_day: date) -> PriceStream:
    week_start_date = get_week_start_day(week_day)
    for day_offset in range(7):
        current_day = week_start_date + timedelta(days=day_offset)

        data_generator = dynamo_cache.get(
            day_data_cache_key(symbol.value, current_day.isoformat())
        )
        yield from data_generator


def has_week_data(symbol: Symbol, day: date) -> bool:
    days_available = 0
    for day_offset in range(7):
        if has_day_data(symbol, day + timedelta(days=day_offset)):
            days_available += 1
    log.info('has_week_data: %s days available', days_available)
    return days_available >= 5


def set_day_cache(symbol: Symbol, day: date, data: list):
    cache_key = day_data_cache_key(symbol.value, day.isoformat())
    meta_key_name = meta_key(cache_key)
    log.info('setting cache %s', cache_key)
    log.info('setting cache meta %s', meta_key_name)
    dynamo_cache.set(cache_key, data)
    dynamo_cache.set_meta(meta_key_name, {'data_counter': len(data)})


def has_day_data(symbol: Symbol, day: date) -> bool:
    """
    externally used to check the availability of the cache
    """

    meta_key_for_day = meta_key(
        day_data_cache_key(
            symbol.value, day.isoformat()
        )
    )
    log.info('checking cache by meta %s', meta_key_for_day)
    return dynamo_cache.has_meta(meta_key_for_day)


def day_data_cache_key(symbol_str: str, date_str: str):
    return f'day-data-{symbol_str}-{date_str}'


def lock_key(cache_key: str) -> str:
    """lock key format"""
    return f'{cache_key}-lock'


def meta_key(cache_key: str) -> str:
    """meta key format"""
    return f'{cache_key}-meta'
