import logging
from datetime import timedelta

from django.utils import timezone
from trends.models import PERIOD_CHOICES, TrendResult
from trends.trends import TREND_REGISTRY

logger = logging.getLogger(__name__)

PERIOD_DAYS = {
    "last_7": 7,
    "last_30": 30,
    "last_90": 90,
    "last_year": 365,
}

PERIOD_LABELS = dict(PERIOD_CHOICES)

TIME_BOUND_TRENDS = {
    "activity-distribution",
    "concurrent-listening",
    "fasting",
    "mood-by-time",
    "mood-distribution",
    "mood-streaks",
    "mood-trajectory",
    "mood-weather",
    "peak-hours",
    "reading-pace-vs-activity",
    "time-of-day-categories",
    "trending-up",
    "weekly-rhythm",
}

TREND_PERIOD_OVERRIDES = {
    "trending-up": ["last_30", "last_90", "last_year"],
}


def get_disabled_trends(user):
    profile = user.profile
    if profile.trends_disabled:
        return set(TREND_REGISTRY.keys())
    return set(profile.disabled_trends or [])


def get_supported_periods(trend_slug):
    if trend_slug in TREND_PERIOD_OVERRIDES:
        slugs = TREND_PERIOD_OVERRIDES[trend_slug]
        return {s: PERIOD_LABELS[s] for s in slugs}
    return dict(PERIOD_LABELS)


def get_period_days(period):
    return PERIOD_DAYS.get(period)


def get_date_range(period):
    days = get_period_days(period)
    if days is None:
        return None, None
    now = timezone.now()
    return now - timedelta(days=days), now


def get_period_nav(current_period, trend_slug):
    supported = get_supported_periods(trend_slug)
    keys = list(supported.keys())
    try:
        idx = keys.index(current_period)
    except ValueError:
        return None, None
    prev_period = keys[idx - 1] if idx > 0 else None
    next_period = keys[idx + 1] if idx < len(keys) - 1 else None
    return prev_period, next_period


def compute_and_save_trend(user, slug, period="last_30"):
    """Compute a single trend for a given period and persist the result.

    Returns elapsed seconds on success, raises on failure.
    """
    from trends.trends import TREND_REGISTRY

    fn = TREND_REGISTRY[slug]
    start = timezone.now()
    data = fn(user, period=period)
    TrendResult.objects.update_or_create(
        user=user,
        trend_slug=slug,
        period=period,
        defaults={"data": data, "computed_at": timezone.now()},
    )
    return (timezone.now() - start).total_seconds()
