"""apps.forms 单元测试：线索提交 API（B2B 官网核心转化路径，测试覆盖率要求较高）。"""
from datetime import timedelta

import pytest
from django.core.cache import cache
from django.utils import timezone
from rest_framework.test import APIClient

from apps.forms.models import (
    FormDefinition,
    FormDefinitionField,
    Lead,
    LeadDeletionRequest,
)

pytestmark = pytest.mark.django_db


@pytest.fixture(autouse=True)
def _clear_throttle_cache():
    """ScopedRateThrottle 依赖默认缓存记录请求次数，避免测试间相互影响（forms scope 限流 5/min）。"""
    cache.clear()
    yield


@pytest.fixture
def contact_form():
    form_def = FormDefinition.objects.create(
        name="联系我们",
        success_message="提交成功，我们会尽快联系您。",
    )
    FormDefinitionField.objects.create(
        form=form_def, label="姓名", field_key="name", field_type="text", required=True
    )
    return form_def


def test_lead_submit_creates_lead_and_returns_success_message(contact_form):
    client = APIClient()
    response = client.post(
        "/api/v1/custom/leads/",
        {
            "form_id": contact_form.pk,
            "data": {"name": "张三"},
            "source_url": "https://example.com/contact",
        },
        format="json",
    )

    assert response.status_code == 201
    assert response.data["success"] is True
    assert response.data["message"] == contact_form.success_message

    lead = Lead.objects.get()
    assert lead.form_id == contact_form.pk
    assert lead.data == {"name": "张三"}
    assert lead.source_url == "https://example.com/contact"


def test_lead_submit_returns_404_for_unknown_form():
    client = APIClient()
    response = client.post(
        "/api/v1/custom/leads/",
        {"form_id": 9999, "data": {}},
        format="json",
    )

    assert response.status_code == 404
    assert response.data["error"]["code"] == "NOT_FOUND"


def test_lead_submit_requires_form_id():
    client = APIClient()
    response = client.post(
        "/api/v1/custom/leads/",
        {"data": {"name": "张三"}},
        format="json",
    )

    assert response.status_code == 400


def test_lead_submit_honeypot_filled_silently_rejects_without_creating_lead(
    contact_form,
):
    """蜜罐字段非空视为机器人：返回“成功”假象但不落库、不发通知邮件。"""
    client = APIClient()
    response = client.post(
        "/api/v1/custom/leads/",
        {
            "form_id": contact_form.pk,
            "data": {"name": "张三"},
            "website": "http://spam.example.com",
        },
        format="json",
    )

    assert response.status_code == 201
    assert response.data["success"] is True
    assert not Lead.objects.exists()


# --- PIPL 数据删除权（详见设计文档 §2.15） ---


def test_deletion_request_returns_generic_message_and_sends_email(
    contact_form, mailoutbox
):
    Lead.objects.create(
        form=contact_form,
        data={"name": "张三", "email": "zhangsan@example.com"},
    )

    client = APIClient()
    response = client.post(
        "/api/v1/custom/leads/deletion-requests/",
        {"contact": "zhangsan@example.com"},
        format="json",
    )

    assert response.status_code == 202
    assert LeadDeletionRequest.objects.filter(contact="zhangsan@example.com").exists()
    assert len(mailoutbox) == 1
    assert mailoutbox[0].to == ["zhangsan@example.com"]


def test_deletion_request_returns_same_generic_message_for_unknown_contact(mailoutbox):
    """未提交过表单的邮箱也返回相同提示，避免探测。"""
    client = APIClient()
    response_known = client.post(
        "/api/v1/custom/leads/deletion-requests/",
        {"contact": "known@example.com"},
        format="json",
    )
    response_unknown = client.post(
        "/api/v1/custom/leads/deletion-requests/",
        {"contact": "unknown@example.com"},
        format="json",
    )

    assert response_known.status_code == response_unknown.status_code == 202
    assert response_known.data["message"] == response_unknown.data["message"]


def test_deletion_confirm_deletes_matching_leads_only(contact_form):
    matching_lead = Lead.objects.create(
        form=contact_form,
        data={"name": "张三", "email": "zhangsan@example.com"},
    )
    other_lead = Lead.objects.create(
        form=contact_form,
        data={"name": "李四", "email": "lisi@example.com"},
    )
    deletion_request = LeadDeletionRequest.objects.create(contact="zhangsan@example.com")

    client = APIClient()
    response = client.post(
        "/api/v1/custom/leads/deletion-requests/confirm/",
        {"token": str(deletion_request.token)},
        format="json",
    )

    assert response.status_code == 200
    assert response.data["success"] is True
    assert response.data["deleted_count"] == 1
    assert not Lead.objects.filter(pk=matching_lead.pk).exists()
    assert Lead.objects.filter(pk=other_lead.pk).exists()

    deletion_request.refresh_from_db()
    assert deletion_request.status == LeadDeletionRequest.STATUS_COMPLETED
    assert deletion_request.deleted_count == 1
    assert deletion_request.completed_at is not None


def test_deletion_confirm_invalid_token_returns_404():
    client = APIClient()
    response = client.post(
        "/api/v1/custom/leads/deletion-requests/confirm/",
        {"token": "00000000-0000-0000-0000-000000000000"},
        format="json",
    )

    assert response.status_code == 404
    assert response.data["error"]["code"] == "INVALID_TOKEN"


def test_deletion_confirm_expired_token_returns_400():
    deletion_request = LeadDeletionRequest.objects.create(contact="zhangsan@example.com")
    LeadDeletionRequest.objects.filter(pk=deletion_request.pk).update(
        requested_at=timezone.now() - timedelta(hours=25)
    )

    client = APIClient()
    response = client.post(
        "/api/v1/custom/leads/deletion-requests/confirm/",
        {"token": str(deletion_request.token)},
        format="json",
    )

    assert response.status_code == 400
    assert response.data["error"]["code"] == "TOKEN_EXPIRED"

    deletion_request.refresh_from_db()
    assert deletion_request.status == LeadDeletionRequest.STATUS_EXPIRED


def test_deletion_confirm_already_processed_returns_400():
    deletion_request = LeadDeletionRequest.objects.create(
        contact="zhangsan@example.com",
        status=LeadDeletionRequest.STATUS_COMPLETED,
    )

    client = APIClient()
    response = client.post(
        "/api/v1/custom/leads/deletion-requests/confirm/",
        {"token": str(deletion_request.token)},
        format="json",
    )

    assert response.status_code == 400
    assert response.data["error"]["code"] == "ALREADY_PROCESSED"
