"""
Contract Tests: Pet Owners API

Endpoint: /mascotas/api/v1/pet-owners/
App: mascotas

Related Tickets:
- VET-536: Paso 0 - Test creación del petowner invitado
- VET-535: Establecer y definir test para las apis vinculadas al procesos de solicitar turno general

Context: In the turnero general flow (guest booking), a "guest" pet owner is created
with a mock email (e.g., invitado-1759415377297@example.com). This user is fundamental
for subsequent steps as it provides the address used to filter available services.

TBD: PetOwnerViewSet needs pagination - currently loads all records on list().
     See mascotas/views/api/v1/views/petowner_views.py:72
     Using email filter in tests to avoid loading 14k+ records.
"""

import time
from ..base import ContractTestCase
from ..endpoints import Endpoints
from ..helpers import sample_pet_owner


class TestPetOwnerCreate(ContractTestCase):
    """POST /mascotas/api/v1/pet-owners/

    VET-536: Tests for guest petowner creation (Step 0 of turnero flow)
    """

    def test_create_returns_201(self):
        """
        Creating a pet owner returns 201 with the created resource.

        Request (from production turnero):
            POST /mascotas/api/v1/pet-owners/
            {
                "first_name": "Juan",
                "last_name": "Pérez",
                "email": "invitado-1733929847293@example.com",
                "phone": "1155667788",
                "address": "Av. Santa Fe 1234, Buenos Aires",
                "geo_latitude": -34.5955,
                "geo_longitude": -58.4166
            }

        Response (201):
            {
                "id": 12345,
                "first_name": "Juan",
                "last_name": "Pérez",
                "email": "invitado-1733929847293@example.com",
                "phone": "1155667788",
                "address": "Av. Santa Fe 1234, Buenos Aires",
                "geo_latitude": -34.5955,
                "geo_longitude": -58.4166,
                "pets": [],
                "created_at": "2024-12-11T15:30:47.293Z"
            }
        """
        data = sample_pet_owner()

        response = self.post(Endpoints.PET_OWNERS, data)

        self.assert_status(response, 201)
        self.assert_has_fields(response.data, "id", "email", "first_name", "last_name")
        self.assertEqual(response.data["email"], data["email"])

    def test_requires_email(self):
        """
        Pet owner creation requires email (current behavior).

        Note: The turnero guest flow uses a mock email created by frontend
        (e.g., invitado-1759415377297@example.com). The API always requires email.
        This test ensures the contract enforcement - no petowner without email.
        """
        data = {
            "address": "Av. Corrientes 1234",
            "first_name": "Invitado",
            "last_name": str(int(time.time())),
        }

        response = self.post(Endpoints.PET_OWNERS, data)

        self.assert_status(response, 400)

    def test_duplicate_email_returns_existing(self):
        """
        Creating pet owner with existing email returns the existing record.

        Note: API has upsert behavior - returns 200 with existing record,
        not 400 error. This allows frontend to "create or get" in one call.
        Important for guest flow - if user refreshes/retries, we don't create duplicates.
        """
        data = sample_pet_owner()
        first_response = self.post(Endpoints.PET_OWNERS, data)
        first_id = first_response.data["id"]

        response = self.post(Endpoints.PET_OWNERS, data)  # Same email

        # Returns 200 with existing record (upsert behavior)
        self.assert_status(response, 200)
        self.assertEqual(response.data["id"], first_id)

    def test_address_and_geolocation_persisted(self):
        """
        Pet owner address and geolocation coordinates are persisted correctly.

        The address is critical for the turnero flow - it's used to filter available
        services by location. Geolocation (lat/lng) may be obtained from Google Maps API.
        """
        data = sample_pet_owner()

        response = self.post(Endpoints.PET_OWNERS, data)

        self.assert_status(response, 201)
        self.assert_has_fields(response.data, "address", "geo_latitude", "geo_longitude")
        self.assertEqual(response.data["address"], data["address"])
        # Verify geolocation fields are numeric (not null/empty)
        self.assertIsNotNone(response.data.get("geo_latitude"))
        self.assertIsNotNone(response.data.get("geo_longitude"))


class TestPetOwnerRetrieve(ContractTestCase):
    """GET /mascotas/api/v1/pet-owners/{id}/"""

    def test_get_by_id_returns_200(self):
        """GET pet owner by ID returns owner details"""
        # Create owner first
        data = sample_pet_owner()
        create_response = self.post(Endpoints.PET_OWNERS, data)
        owner_id = create_response.data["id"]

        response = self.get(Endpoints.PET_OWNER_DETAIL.format(id=owner_id))

        self.assert_status(response, 200)
        self.assertEqual(response.data["id"], owner_id)
        self.assert_has_fields(response.data, "id", "first_name", "last_name", "address", "pets")

    def test_nonexistent_returns_404(self):
        """GET non-existent owner returns 404"""
        response = self.get(Endpoints.PET_OWNER_DETAIL.format(id=999999))

        self.assert_status(response, 404)


class TestPetOwnerList(ContractTestCase):
    """GET /mascotas/api/v1/pet-owners/"""

    def test_list_with_email_filter_returns_200(self):
        """GET pet owners filtered by email returns 200"""
        # Filter by email to avoid loading 14k+ records (no pagination on this endpoint)
        response = self.get(Endpoints.PET_OWNERS, params={"email": "nonexistent@test.com"})

        self.assert_status(response, 200)

    def test_list_filter_by_email_works(self):
        """Can filter pet owners by email"""
        # Create a pet owner first
        data = sample_pet_owner()
        self.post(Endpoints.PET_OWNERS, data)

        # Filter by that email
        response = self.get(Endpoints.PET_OWNERS, params={"email": data["email"]})

        self.assert_status(response, 200)
        # Should find exactly one
        results = response.data if isinstance(response.data, list) else response.data.get("results", [])
        self.assertEqual(len(results), 1)
        self.assertEqual(results[0]["email"], data["email"])
