"""
Pricing engine for discourse tolls.

Calculates dynamic pricing based on:
- Base cost per action
- Progressive cost (more comments in same context = higher price)
- Trust discount (higher trust score = lower price)
- Cooldown bonus (waiting between actions = cheaper)
"""

from __future__ import annotations

import math
import time
from dataclasses import dataclass, field
from typing import Optional


@dataclass
class TrustDiscountConfig:
    enabled: bool = True
    free_above: int = 80        # Trust score >= this = free
    discount_above: int = 30    # Trust score >= this = discounted
    discount_percent: int = 50  # Percent discount for trusted agents


@dataclass
class CooldownConfig:
    enabled: bool = True
    window_ms: int = 60_000     # 1 minute
    bonus_percent: int = 25     # Discount if last action was > window ago


@dataclass
class PricingConfig:
    base_sats: int = 1
    progressive_multiplier: float = 1.5
    progressive_cap: int = 50
    trust_discount: TrustDiscountConfig = field(default_factory=TrustDiscountConfig)
    cooldown: CooldownConfig = field(default_factory=CooldownConfig)


@dataclass
class PriceResult:
    sats: int
    breakdown: dict


class PricingEngine:
    def __init__(self, config: Optional[PricingConfig] = None):
        self.config = config or PricingConfig()
        self._activity: dict[str, list[dict]] = {}  # context_id → [{agent, timestamp}]
        self._agent_last_action: dict[str, float] = {}  # agent_id → timestamp_ms

    def calculate(
        self,
        agent_id: str,
        context_id: str,
        trust_score: Optional[int] = None,
        dry_run: bool = False,
    ) -> PriceResult:
        cfg = self.config
        breakdown: dict = {"base": cfg.base_sats}
        now_ms = time.time() * 1000

        # --- Progressive pricing ---
        context_activity = self._activity.get(context_id, [])
        agent_actions = sum(1 for a in context_activity if a["agent"] == agent_id)

        progressive_cost = cfg.base_sats
        if agent_actions > 0:
            progressive_cost = min(
                math.ceil(cfg.base_sats * (cfg.progressive_multiplier ** agent_actions)),
                cfg.progressive_cap,
            )
        breakdown["progressive"] = progressive_cost
        breakdown["prior_actions_in_context"] = agent_actions

        price = progressive_cost

        # --- Trust discount ---
        td = cfg.trust_discount
        if td.enabled and trust_score is not None:
            breakdown["trust_score"] = trust_score
            if trust_score >= td.free_above:
                breakdown["trust_discount"] = price
                price = 0
            elif trust_score >= td.discount_above:
                discount = price * td.discount_percent // 100
                breakdown["trust_discount"] = discount
                price = max(1, price - discount)
            else:
                breakdown["trust_discount"] = 0

        # --- Cooldown bonus ---
        cd = cfg.cooldown
        if cd.enabled and price > 0:
            last_action = self._agent_last_action.get(agent_id)
            if last_action is None or (now_ms - last_action) > cd.window_ms:
                bonus = price * cd.bonus_percent // 100
                breakdown["cooldown_bonus"] = bonus
                price = max(1, price - bonus) if bonus < price else price
            else:
                breakdown["cooldown_bonus"] = 0

        breakdown["final"] = price

        # Record activity
        if not dry_run:
            self._activity.setdefault(context_id, []).append(
                {"agent": agent_id, "timestamp": now_ms}
            )
            self._agent_last_action[agent_id] = now_ms

        return PriceResult(sats=price, breakdown=breakdown)

    def get_activity_count(self, agent_id: str, context_id: str) -> int:
        return sum(
            1 for a in self._activity.get(context_id, []) if a["agent"] == agent_id
        )

    def cleanup(self, max_age_ms: int = 86_400_000) -> None:
        cutoff = time.time() * 1000 - max_age_ms
        for key in list(self._activity.keys()):
            filtered = [a for a in self._activity[key] if a["timestamp"] > cutoff]
            if filtered:
                self._activity[key] = filtered
            else:
                del self._activity[key]
        for agent in list(self._agent_last_action.keys()):
            if self._agent_last_action[agent] < cutoff:
                del self._agent_last_action[agent]

    def stats(self) -> dict:
        total_actions = sum(len(v) for v in self._activity.values())
        return {
            "contexts": len(self._activity),
            "agents": len(self._agent_last_action),
            "total_actions": total_actions,
        }

    def reset(self) -> None:
        self._activity.clear()
        self._agent_last_action.clear()
