"""Simple adaptive rate limiting — ~15 lines of core logic.

From the spec: "That's it. Not 2-3 weeks. ~15 lines. Ships Day 1."

Logic:
- Start at 15 invitations/day
- If acceptance rate >30%: increase by 5 (cap 50)
- If acceptance rate <15%: decrease by 5 (floor 10)
- If blocked: halve (floor 5)
- Hard weekly cap: 100

Working hours: 8 AM - 6 PM, weekdays only.
Randomized delays: 15-45 minutes between sends.
"""

from __future__ import annotations

import logging
import random
from datetime import datetime
from typing import Any

from .. import constants
from ..config import load_config
from ..db.queries import get_rate_limit_today, update_daily_limit

logger = logging.getLogger(__name__)


def adjust_daily_limit(current: int, stats: dict[str, Any]) -> int:
    """The entire adaptive system — ~15 lines.

    Args:
        current: Current daily limit
        stats: Dict with 'sent', 'accepted', 'blocked' keys

    Returns:
        New daily limit
    """
    if stats.get("blocked"):
        return max(constants.BLOCK_HALVE_FLOOR, current // 2)

    sent = stats.get("sent", 0)
    accepted = stats.get("accepted", 0)

    if sent == 0:
        return current

    rate = accepted / sent

    if rate > constants.ACCEPTANCE_RATE_RAMP_UP and current < constants.MAX_DAILY_INVITATIONS:
        return current + constants.RAMP_STEP

    if rate < constants.ACCEPTANCE_RATE_PULL_BACK:
        return max(constants.MIN_DAILY_LIMIT, current - constants.RAMP_STEP)

    return current


def can_send_now() -> tuple[bool, str]:
    """Check if we can send an invitation right now.

    Returns (can_send, reason_if_not).
    """
    now = datetime.now()
    cfg = load_config()
    working_hours = cfg.get("working_hours", {})

    start_hour = working_hours.get("start", constants.DEFAULT_START_HOUR)
    end_hour = working_hours.get("end", constants.DEFAULT_END_HOUR)
    active_days = working_hours.get("days", constants.DEFAULT_ACTIVE_DAYS)

    # Check day of week (0=Monday)
    if now.weekday() not in active_days:
        return False, f"Outside working days. Active days: {active_days}"

    # Check working hours
    if now.hour < start_hour:
        return False, f"Before working hours ({start_hour}:00). Queued for later."
    if now.hour >= end_hour:
        return False, f"After working hours ({end_hour}:00). Queued for tomorrow."

    # Check daily limit
    rate_data = get_rate_limit_today()
    sent_today = rate_data.get("sent", 0)
    daily_limit = rate_data.get("daily_limit", constants.INITIAL_DAILY_INVITATIONS)

    if sent_today >= daily_limit:
        return False, f"Daily limit reached ({sent_today}/{daily_limit}). Resumes tomorrow."

    # Check weekly cap
    # TODO: Sum last 7 days from rate_limits table
    # For now, daily limit is the main guard

    return True, ""


def get_next_delay() -> int:
    """Get randomized delay in seconds for the next send.

    Returns a random delay between MIN_DELAY_MINUTES and MAX_DELAY_MINUTES.
    """
    min_secs = constants.MIN_DELAY_MINUTES * 60
    max_secs = constants.MAX_DELAY_MINUTES * 60
    return random.randint(min_secs, max_secs)


def update_limits_after_send(blocked: bool = False) -> int:
    """Update rate limits after a send attempt. Returns new daily limit."""
    rate_data = get_rate_limit_today()

    stats = {
        "sent": rate_data.get("sent", 0),
        "accepted": rate_data.get("accepted", 0),
        "blocked": blocked,
    }

    new_limit = adjust_daily_limit(rate_data.get("daily_limit", 15), stats)

    if new_limit != rate_data.get("daily_limit"):
        update_daily_limit(new_limit)
        logger.info(f"Daily limit adjusted: {rate_data.get('daily_limit')} → {new_limit}")

    return new_limit
