import random, threading
from config import CONFIG

SALE_CC = {99: 109}
SEMI_UPSELL = {
    125:141, 150:168, 175:142, 199:143, 200:137, 225:144, 250:138, 297:145,
    350:146, 397:147, 399:170, 425:148, 450:171, 499:149, 500:140, 525:150,
    575:151, 600:165, 650:166, 700:152, 750:187, 799:153, 850:167, 875:154,
    950:155, 1000:156, 1150:157, 1200:173, 1299:158, 1350:174, 1399:159,
    1475:160, 1500:175, 1700:161, 1800:186, 1925:162, 2000:176, 2100:177,
    2225:163, 2350:191, 2499:164, 4997:192, 5000:188, 7000:189, 10000:190,
}
ALL_AMOUNTS = sorted(list(SALE_CC.keys()) + list(SEMI_UPSELL.keys()))
HIGH_VALUE_PROVIDERS = ["fanbasis2", "fanbasis"]

# URL patterns per provider
SALE_CC_URLS = {
    "fanbasis":  "https://payment.parvaty.com/salescc/?ref=GE&product_id={pid}&provider=fanbasis&T=GE",
    "fanbasis2": "https://payment.parvaty.com/salescc/?ref=GE&product_id={pid}&provider=fanbasis2&T=GE",
    "whop":      "https://payment.parvaty.com/salescc/?ref=GE&product_id={pid}&provider=whop&T=GE",
}
SEMI_URLS = {
    "fanbasis":  "https://payment.parvaty.com/sales?ref=GE&product_id={pid}&provider=fanbasis&semi=true&T=GE",
    "fanbasis2": "https://payment.parvaty.com/sales?ref=GE&product_id={pid}&provider=fanbasis2&semi=true&T=GE&T=GE",
    "whop":      "https://payment.parvaty.com/sales?ref=GE&product_id={pid}&provider=whop&semi=true&T=GE&T=GE",
}

class LinkResolver:
    def __init__(self):
        self.providers = CONFIG["providers"]
        self._lock = threading.Lock()
        self._usage = {p: 0 for p in self.providers}

    def _pick_provider(self, allowed):
        with self._lock:
            candidates = {p: self._usage.get(p, 0) for p in allowed if p in self._usage}
            if not candidates: return random.choice(allowed)
            min_count = min(candidates.values())
            least_used = [p for p, c in candidates.items() if c == min_count]
            chosen = random.choice(least_used)
            self._usage[chosen] = self._usage.get(chosen, 0) + 1
            return chosen

    def _build_url(self, amount, pid, provider):
        if amount in SALE_CC:
            return SALE_CC_URLS[provider].format(pid=pid)
        return SEMI_URLS[provider].format(pid=pid)

    def _get_pid(self, amount):
        if amount in SALE_CC: return SALE_CC[amount]
        if amount in SEMI_UPSELL: return SEMI_UPSELL[amount]
        return None

    def _get_allowed_providers(self, amount):
        if amount > 2499: return HIGH_VALUE_PROVIDERS
        return self.providers

    def get_link(self, amount, forced_provider=None):
        pid = self._get_pid(amount)
        if pid is None: return None
        allowed = self._get_allowed_providers(amount)
        if forced_provider and forced_provider in allowed:
            provider = forced_provider
        elif forced_provider and forced_provider not in allowed:
            provider = forced_provider  # respect agent override even for high-value
        else:
            provider = self._pick_provider(allowed)
        url = self._build_url(amount, pid, provider)
        link_type = "Sale CC" if amount in SALE_CC else "CC Semi Upsell"
        return {"provider": provider, "url": url, "type": link_type, "amount": amount}

    def smart_resolve(self, requested_amount, forced_provider=None):
        # 1. Exact match
        if requested_amount in ALL_AMOUNTS:
            link = self.get_link(requested_amount, forced_provider=forced_provider)
            if link:
                link["note"] = None
                return [link]

        # 2. Find nearest in BOTH directions, pick closest
        nearest_higher = None
        nearest_lower = None
        for a in ALL_AMOUNTS:
            if a >= requested_amount and nearest_higher is None:
                nearest_higher = a
            if a <= requested_amount:
                nearest_lower = a

        diff_higher = (nearest_higher - requested_amount) if nearest_higher else float('inf')
        diff_lower = (requested_amount - nearest_lower) if nearest_lower else float('inf')

        # Pick the one with smallest difference (within $50)
        if diff_lower <= diff_higher and diff_lower <= 50:
            link = self.get_link(nearest_lower, forced_provider=forced_provider)
            if link:
                link["note"] = f"Closest: ${nearest_lower:,} (-${diff_lower})" if diff_lower > 0 else None
                return [link]
        elif diff_higher <= 50:
            link = self.get_link(nearest_higher, forced_provider=forced_provider)
            if link:
                link["note"] = f"Closest: ${nearest_higher:,} (+${diff_higher})" if diff_higher > 0 else None
                return [link]

        # 3. Split into 2 links
        best_combo = None
        best_diff = float('inf')
        for a1 in ALL_AMOUNTS:
            if a1 >= requested_amount:
                break
            remaining = requested_amount - a1
            for a2 in ALL_AMOUNTS:
                total = a1 + a2
                diff = abs(total - requested_amount)
                if diff < best_diff:
                    best_diff = diff
                    best_combo = (a1, a2, total, diff)
                if a2 >= remaining:
                    break

        if best_combo and best_diff <= 100:
            a1, a2, total, diff = best_combo
            link1 = self.get_link(a1, forced_provider=forced_provider)
            link2 = self.get_link(a2, forced_provider=forced_provider)
            if link1 and link2:
                sign = "+" if total > requested_amount else "-"
                link1["note"] = f"Split: ${a1:,} + ${a2:,} = ${total:,} ({sign}${diff})"
                link2["note"] = None
                return [link1, link2]

        # 4. Fallback
        if nearest_higher:
            link = self.get_link(nearest_higher, forced_provider=forced_provider)
            if link:
                link["note"] = f"Nearest: ${nearest_higher:,} (+${diff_higher})"
                return [link]
        return None

    def get_stats(self):
        with self._lock:
            total = sum(self._usage.values()) or 1
            return {p: {"count": c, "pct": round(c/total*100, 1)} for p, c in self._usage.items()}

    def get_available_amounts(self):
        return ALL_AMOUNTS
