# tests/unit/models/database/test_customer.py
"""Unit tests for Customer and CustomerAddress database models."""

import pytest

from app.modules.customers.models.customer import Customer, CustomerAddress


@pytest.mark.unit
@pytest.mark.database
class TestCustomerModel:
    """Test Customer model."""

    def test_customer_creation(self, db, test_store):
        """Test Customer model with store isolation."""
        customer = Customer(
            store_id=test_store.id,
            email="customer@example.com",
            hashed_password="hashed_password",  # noqa: SEC001
            first_name="John",
            last_name="Doe",
            customer_number="CUST001",
            is_active=True,
        )

        db.add(customer)
        db.commit()
        db.refresh(customer)

        assert customer.id is not None
        assert customer.store_id == test_store.id
        assert customer.email == "customer@example.com"
        assert customer.customer_number == "CUST001"
        assert customer.first_name == "John"
        assert customer.last_name == "Doe"
        assert customer.store.store_code == test_store.store_code

    def test_customer_default_values(self, db, test_store):
        """Test Customer model default values."""
        customer = Customer(
            store_id=test_store.id,
            email="defaults@example.com",
            hashed_password="hash",  # noqa: SEC001
            customer_number="CUST_DEFAULTS",
        )
        db.add(customer)
        db.commit()
        db.refresh(customer)

        assert customer.is_active is True  # Default
        assert customer.marketing_consent is False  # Default

    def test_customer_full_name_property(self, db, test_store):
        """Test Customer full_name computed property."""
        customer = Customer(
            store_id=test_store.id,
            email="fullname@example.com",
            hashed_password="hash",  # noqa: SEC001
            customer_number="CUST_FULLNAME",
            first_name="Jane",
            last_name="Smith",
        )
        db.add(customer)
        db.commit()
        db.refresh(customer)

        assert customer.full_name == "Jane Smith"

    def test_customer_full_name_fallback_to_email(self, db, test_store):
        """Test Customer full_name falls back to email when names not set."""
        customer = Customer(
            store_id=test_store.id,
            email="noname@example.com",
            hashed_password="hash",  # noqa: SEC001
            customer_number="CUST_NONAME",
        )
        db.add(customer)
        db.commit()
        db.refresh(customer)

        assert customer.full_name == "noname@example.com"

    def test_customer_optional_fields(self, db, test_store):
        """Test Customer with optional fields."""
        customer = Customer(
            store_id=test_store.id,
            email="optional@example.com",
            hashed_password="hash",  # noqa: SEC001
            customer_number="CUST_OPT",
            phone="+352123456789",
            preferences={"language": "en", "currency": "EUR"},
            marketing_consent=True,
        )
        db.add(customer)
        db.commit()
        db.refresh(customer)

        assert customer.phone == "+352123456789"
        assert customer.preferences == {"language": "en", "currency": "EUR"}
        assert customer.marketing_consent is True

    def test_customer_store_relationship(self, db, test_store):
        """Test Customer-Store relationship."""
        customer = Customer(
            store_id=test_store.id,
            email="relationship@example.com",
            hashed_password="hash",  # noqa: SEC001
            customer_number="CUST_REL",
        )
        db.add(customer)
        db.commit()
        db.refresh(customer)

        assert customer.store is not None
        assert customer.store.id == test_store.id


@pytest.mark.unit
@pytest.mark.database
class TestCustomerAddressModel:
    """Test CustomerAddress model."""

    def test_customer_address_creation(self, db, test_store, test_customer):
        """Test CustomerAddress model."""
        address = CustomerAddress(
            store_id=test_store.id,
            customer_id=test_customer.id,
            address_type="shipping",
            first_name="John",
            last_name="Doe",
            address_line_1="123 Main St",
            city="Luxembourg",
            postal_code="L-1234",
            country_name="Luxembourg",
            country_iso="LU",
            is_default=True,
        )

        db.add(address)
        db.commit()
        db.refresh(address)

        assert address.id is not None
        assert address.store_id == test_store.id
        assert address.customer_id == test_customer.id
        assert address.address_type == "shipping"
        assert address.is_default is True

    def test_customer_address_types(self, db, test_store, test_customer):
        """Test CustomerAddress with different address types."""
        shipping_address = CustomerAddress(
            store_id=test_store.id,
            customer_id=test_customer.id,
            address_type="shipping",
            first_name="John",
            last_name="Doe",
            address_line_1="123 Shipping St",
            city="Luxembourg",
            postal_code="L-1234",
            country_name="Luxembourg",
            country_iso="LU",
        )
        db.add(shipping_address)

        billing_address = CustomerAddress(
            store_id=test_store.id,
            customer_id=test_customer.id,
            address_type="billing",
            first_name="John",
            last_name="Doe",
            address_line_1="456 Billing Ave",
            city="Luxembourg",
            postal_code="L-5678",
            country_name="Luxembourg",
            country_iso="LU",
        )
        db.add(billing_address)
        db.commit()

        assert shipping_address.address_type == "shipping"
        assert billing_address.address_type == "billing"

    def test_customer_address_optional_fields(self, db, test_store, test_customer):
        """Test CustomerAddress with optional fields."""
        address = CustomerAddress(
            store_id=test_store.id,
            customer_id=test_customer.id,
            address_type="shipping",
            first_name="John",
            last_name="Doe",
            company="ACME Corp",
            address_line_1="123 Main St",
            address_line_2="Suite 100",
            city="Luxembourg",
            postal_code="L-1234",
            country_name="Luxembourg",
            country_iso="LU",
        )
        db.add(address)
        db.commit()
        db.refresh(address)

        assert address.company == "ACME Corp"
        assert address.address_line_2 == "Suite 100"

    def test_customer_address_default_values(self, db, test_store, test_customer):
        """Test CustomerAddress default values."""
        address = CustomerAddress(
            store_id=test_store.id,
            customer_id=test_customer.id,
            address_type="shipping",
            first_name="John",
            last_name="Doe",
            address_line_1="123 Main St",
            city="Luxembourg",
            postal_code="L-1234",
            country_name="Luxembourg",
            country_iso="LU",
        )
        db.add(address)
        db.commit()
        db.refresh(address)

        assert address.is_default is False  # Default

    def test_customer_address_relationships(self, db, test_store, test_customer):
        """Test CustomerAddress relationships."""
        address = CustomerAddress(
            store_id=test_store.id,
            customer_id=test_customer.id,
            address_type="shipping",
            first_name="John",
            last_name="Doe",
            address_line_1="123 Main St",
            city="Luxembourg",
            postal_code="L-1234",
            country_name="Luxembourg",
            country_iso="LU",
        )
        db.add(address)
        db.commit()
        db.refresh(address)

        assert address.customer is not None
        assert address.customer.id == test_customer.id
