from test_receivables import h, setup_sale


pytest_plugins = ("test_workspace",)


def test_email_debt_reminder_and_history(
    client,
    verified_user,
    monkeypatch,
):
    business_id, customer, _, _ = setup_sale(
        client,
        verified_user,
        "0",
        "reminder-email",
    )

    customer_id = customer["id"]

    update = client.patch(
        f"/api/businesses/{business_id}/customers/{customer_id}",
        json={
            "email": "customer@example.test",
        },
        headers=h(verified_user),
    )

    assert update.status_code == 200

    sent = {}

    def fake_send(
        to_email,
        customer_name,
        business_name,
        amount_outstanding,
        due_date=None,
        note=None,
    ):
        sent["to"] = to_email
        sent["customer"] = customer_name
        sent["amount"] = str(amount_outstanding)
        sent["note"] = note

    monkeypatch.setattr(
        "app.api.receivables.send_debt_reminder_email",
        fake_send,
    )

    response = client.post(
        f"/api/businesses/{business_id}/customers/{customer_id}/reminders",
        json={
            "message": "Please settle your balance.",
        },
        headers=h(verified_user),
    )

    assert response.status_code == 201

    reminder = response.json()

    assert reminder["status"] == "SENT"
    assert reminder["recipient"] == "customer@example.test"
    assert reminder["amount_outstanding"] == 100.0
    assert reminder["sent_at"] is not None

    assert sent["to"] == "customer@example.test"
    assert sent["amount"] == "100.00"

    history = client.get(
        f"/api/businesses/{business_id}/receivables/reminders",
        headers=h(verified_user),
    )

    assert history.status_code == 200
    assert len(history.json()) == 1
    assert history.json()[0]["id"] == reminder["id"]

    notifications = client.get(
        f"/api/businesses/{business_id}/notifications",
        params={"category": "DEBT_REMINDER"},
        headers=h(verified_user),
    )

    assert notifications.status_code == 200
    assert len(notifications.json()) == 1


def test_reminder_requires_customer_email(
    client,
    verified_user,
):
    business_id, customer, _, _ = setup_sale(
        client,
        verified_user,
        "0",
        "reminder-no-email",
    )

    response = client.post(
        f"/api/businesses/{business_id}/customers/{customer['id']}/reminders",
        json={},
        headers=h(verified_user),
    )

    assert response.status_code == 422

    history = client.get(
        f"/api/businesses/{business_id}/receivables/reminders",
        headers=h(verified_user),
    )

    assert history.status_code == 200
    assert history.json() == []


def test_provider_failure_is_persisted_and_never_marked_sent(
    client,
    verified_user,
    monkeypatch,
):
    business_id, customer, _, _ = setup_sale(
        client,
        verified_user,
        "0",
        "reminder-provider-failure",
    )
    customer_id = customer["id"]
    assert client.patch(
        f"/api/businesses/{business_id}/customers/{customer_id}",
        json={"email": "failed@example.test"},
        headers=h(verified_user),
    ).status_code == 200

    def fail_send(*_args, **_kwargs):
        raise RuntimeError("provider unavailable: secret detail")

    monkeypatch.setattr(
        "app.api.receivables.send_debt_reminder_email",
        fail_send,
    )
    response = client.post(
        f"/api/businesses/{business_id}/customers/{customer_id}/reminders",
        json={},
        headers=h(verified_user),
    )
    assert response.status_code == 502
    assert "secret detail" not in response.text

    history = client.get(
        f"/api/businesses/{business_id}/receivables/reminders",
        headers=h(verified_user),
    ).json()
    assert len(history) == 1
    assert history[0]["status"] == "FAILED"
    assert history[0]["sent_at"] is None
    assert history[0]["error_code"] == "RuntimeError"

    notifications = client.get(
        f"/api/businesses/{business_id}/notifications",
        params={"category": "DEBT_REMINDER"},
        headers=h(verified_user),
    ).json()
    assert notifications == []


def test_paid_customer_cannot_receive_outstanding_debt_reminder(
    client,
    verified_user,
    monkeypatch,
):
    business_id, customer, _, _ = setup_sale(
        client,
        verified_user,
        "0",
        "reminder-paid",
    )
    receivable = client.get(
        f"/api/businesses/{business_id}/receivables",
        headers=h(verified_user),
    ).json()[0]
    assert client.post(
        f"/api/businesses/{business_id}/receivables/{receivable['id']}/collections",
        json={"amount": "100", "payment_method": "CASH"},
        headers=h(verified_user),
    ).status_code == 201
    assert client.patch(
        f"/api/businesses/{business_id}/customers/{customer['id']}",
        json={"email": "paid@example.test"},
        headers=h(verified_user),
    ).status_code == 200

    called = False
    def fake_send(*_args, **_kwargs):
        nonlocal called
        called = True
    monkeypatch.setattr(
        "app.api.receivables.send_debt_reminder_email",
        fake_send,
    )
    response = client.post(
        f"/api/businesses/{business_id}/customers/{customer['id']}/reminders",
        json={},
        headers=h(verified_user),
    )
    assert response.status_code == 422
    assert called is False


def test_reminders_are_business_isolated(
    client,
    verified_user,
    monkeypatch,
):
    business_id, customer, _, _ = setup_sale(
        client,
        verified_user,
        "0",
        "reminder-isolation",
    )
    assert client.patch(
        f"/api/businesses/{business_id}/customers/{customer['id']}",
        json={"email": "isolated@example.test"},
        headers=h(verified_user),
    ).status_code == 200
    monkeypatch.setattr(
        "app.api.receivables.send_debt_reminder_email",
        lambda *_args, **_kwargs: None,
    )
    assert client.post(
        f"/api/businesses/{business_id}/customers/{customer['id']}/reminders",
        json={},
        headers=h(verified_user),
    ).status_code == 201

    other = client.post(
        "/api/businesses",
        json={"name": "Other Debt Business", "main_branch_name": "Main", "country": "Nigeria", "currency": "NGN", "default_language": "en"},
        headers={**h(verified_user), "Idempotency-Key": "other-debt-reminders"},
    ).json()["business"]["id"]
    assert client.get(
        f"/api/businesses/{other}/receivables/reminders",
        headers=h(verified_user),
    ).json() == []
    assert client.post(
        f"/api/businesses/{other}/customers/{customer['id']}/reminders",
        json={},
        headers=h(verified_user),
    ).status_code == 404
