"""
Capacidades cableadas y apagadas (principio VI).

Lo que se verifica no es que estén apagadas —eso es una línea de configuración—
sino que el **camino de código exista y se recorra igual estando apagado**. Es la
diferencia entre poder encenderlas cambiando una variable y tener que buscar
después dónde había que poner cada control.
"""

import pytest
from django.conf import settings

from apps.billing import limits
from apps.billing.models import ConsumptionMetric, ConsumptionRecord, Plan
from tests.factories import create_account, create_domain

pytestmark = pytest.mark.django_db


def test_the_deferred_capabilities_are_off_by_default():
    assert settings.BILLING_ENABLED is False
    assert settings.TXT_VERIFICATION_ENABLED is False


def test_there_is_a_single_default_plan_and_it_limits_nothing():
    plan = Plan.objects.get(is_default=True)

    assert plan.code == 'unlimited'
    # Nulo es «sin tope». Un cero acá convertiría la capacidad apagada en una
    # que bloquea todo.
    assert plan.max_domains is None
    assert plan.max_monitored_urls is None


def test_every_new_account_ends_up_pointed_at_the_default_plan():
    """
    Se asigna en el alta aunque no se cobre.

    Si se encendiera la facturación sobre cuentas sin plan, habría que
    inventarles uno a posteriori y adivinar cuál les correspondía.
    """
    account = create_account()
    assert account.plan is not None
    assert account.plan.code == 'unlimited'


def test_with_billing_off_it_authorizes_but_records_the_consumption():
    account = create_account()
    domain = create_domain(account)

    decision = limits.check(account, limits.Action.INSPECT_URLS, 40, domain=domain)

    assert decision.allowed
    record = ConsumptionRecord.objects.get(account=account, metric=ConsumptionMetric.INSPECTIONS)
    assert record.amount == 40


def test_the_consumption_accumulates_over_the_period():
    account = create_account()
    domain = create_domain(account)

    limits.check(account, limits.Action.INSPECT_URLS, 10, domain=domain)
    limits.check(account, limits.Action.INSPECT_URLS, 5, domain=domain)

    record = ConsumptionRecord.objects.get(account=account, metric=ConsumptionMetric.INSPECTIONS)
    assert record.amount == 15


def test_turning_on_billing_enforces_the_limit_without_touching_code(settings):
    """
    La prueba de que el cableado sirve: se enciende por configuración.

    No hay que agregar ninguna llamada ni mover ninguna comprobación; el punto
    de control ya estaba puesto y se limitaba a autorizar.
    """
    account = create_account()
    create_domain(account, hostname='uno.test')

    settings.BILLING_ENABLED = True
    account.plan.max_domains = 1
    account.plan.save()

    decision = limits.check(account, limits.Action.ADD_DOMAIN)

    assert not decision
    assert decision.limit == 1
    assert decision.current == 1
    assert 'plan' in decision.reason.lower()


def test_a_rejection_is_also_recorded(settings):
    """
    Un rechazo es información sobre la demanda real.

    Perderla haría que los planes se dimensionen sólo con lo que ya entró, que
    es exactamente la muestra sesgada que el registro viene a evitar.
    """
    account = create_account()
    settings.BILLING_ENABLED = True
    account.plan.max_monitored_urls = 0
    account.plan.save()

    limits.check(account, limits.Action.MONITOR_URLS, 7)

    record = ConsumptionRecord.objects.get(account=account, metric=ConsumptionMetric.MONITORED_URLS)
    assert record.amount == 7
