"""Unit tests for data models."""

from datetime import UTC, datetime

import pytest

from augint_billing_lib.models import Link


@pytest.mark.unit
class TestLinkModel:
    """Test Link model."""

    def test_link_creation_minimal(self):
        """Test creating Link with minimal required fields."""
        link = Link(api_key_id="test_key", stripe_customer_id="cus_test")

        assert link.api_key_id == "test_key"
        assert link.stripe_customer_id == "cus_test"
        assert link.cognito_user_id is None
        assert link.plan == "free"
        assert link.usage_plan_id == "FREE_10K"
        assert link.metered_subscription_item_id is None
        assert link.last_reported_usage_ts is None
        assert link.current_month_reported_units == 0

    def test_link_creation_full(self):
        """Test creating Link with all fields."""
        ts = datetime(2024, 1, 15, 10, 0, 0, tzinfo=UTC)
        link = Link(
            api_key_id="test_key",
            stripe_customer_id="cus_test",
            cognito_user_id="cognito_123",
            plan="metered",
            usage_plan_id="METERED",
            metered_subscription_item_id="si_test",
            last_reported_usage_ts=ts,
            current_month_reported_units=5000,
        )

        assert link.api_key_id == "test_key"
        assert link.stripe_customer_id == "cus_test"
        assert link.cognito_user_id == "cognito_123"
        assert link.plan == "metered"
        assert link.usage_plan_id == "METERED"
        assert link.metered_subscription_item_id == "si_test"
        assert link.last_reported_usage_ts == ts
        assert link.current_month_reported_units == 5000

    def test_link_equality(self):
        """Test Link equality comparison."""
        link1 = Link(api_key_id="test_key", stripe_customer_id="cus_test")
        link2 = Link(api_key_id="test_key", stripe_customer_id="cus_test")
        link3 = Link(api_key_id="different_key", stripe_customer_id="cus_test")

        assert link1 == link2
        assert link1 != link3

    def test_link_mutation(self):
        """Test mutating Link fields."""
        link = Link(api_key_id="test_key", stripe_customer_id="cus_test")

        # Mutate fields
        link.plan = "metered"
        link.usage_plan_id = "METERED"
        link.metered_subscription_item_id = "si_new"
        link.current_month_reported_units = 1000

        assert link.plan == "metered"
        assert link.usage_plan_id == "METERED"
        assert link.metered_subscription_item_id == "si_new"
        assert link.current_month_reported_units == 1000

    def test_link_is_metered(self):
        """Test identifying metered links."""
        free_link = Link(api_key_id="test_key", stripe_customer_id="cus_test", plan="free")

        metered_link = Link(
            api_key_id="test_key",
            stripe_customer_id="cus_test",
            plan="metered",
            metered_subscription_item_id="si_test",
        )

        metered_no_sub = Link(
            api_key_id="test_key",
            stripe_customer_id="cus_test",
            plan="metered",
            metered_subscription_item_id=None,
        )

        # Test is_metered method
        assert not free_link.is_metered()
        assert metered_link.is_metered()
        assert metered_no_sub.is_metered()

    def test_link_is_free(self):
        """Test identifying free links."""
        free_link = Link(api_key_id="test_key", stripe_customer_id="cus_test", plan="free")
        metered_link = Link(api_key_id="test_key", stripe_customer_id="cus_test", plan="metered")

        assert free_link.is_free()
        assert not metered_link.is_free()

    def test_link_can_report_usage(self):
        """Test checking if link can report usage."""
        # Can't report - free plan
        free_link = Link(api_key_id="test_key", stripe_customer_id="cus_test", plan="free")
        assert not free_link.can_report_usage()

        # Can't report - metered but no subscription item
        metered_no_sub = Link(
            api_key_id="test_key",
            stripe_customer_id="cus_test",
            plan="metered",
            metered_subscription_item_id=None,
        )
        assert not metered_no_sub.can_report_usage()

        # Can report - metered with subscription item
        metered_link = Link(
            api_key_id="test_key",
            stripe_customer_id="cus_test",
            plan="metered",
            metered_subscription_item_id="si_test",
        )
        assert metered_link.can_report_usage()

    def test_link_needs_month_reset(self):
        """Test checking if monthly usage counter needs reset."""
        now = datetime(2024, 2, 15, 10, 0, 0, tzinfo=UTC)

        # No timestamp - doesn't need reset
        link_no_ts = Link(
            api_key_id="test_key",
            stripe_customer_id="cus_test",
            last_reported_usage_ts=None,
            current_month_reported_units=100,
        )
        assert not link_no_ts.needs_month_reset(now)

        # Same month - doesn't need reset
        same_month = datetime(2024, 2, 10, 10, 0, 0, tzinfo=UTC)
        link_same_month = Link(
            api_key_id="test_key",
            stripe_customer_id="cus_test",
            last_reported_usage_ts=same_month,
            current_month_reported_units=100,
        )
        assert not link_same_month.needs_month_reset(now)

        # Previous month - needs reset
        prev_month = datetime(2024, 1, 15, 10, 0, 0, tzinfo=UTC)
        link_prev_month = Link(
            api_key_id="test_key",
            stripe_customer_id="cus_test",
            last_reported_usage_ts=prev_month,
            current_month_reported_units=100,
        )
        assert link_prev_month.needs_month_reset(now)

        # Previous year - needs reset
        prev_year = datetime(2023, 12, 15, 10, 0, 0, tzinfo=UTC)
        link_prev_year = Link(
            api_key_id="test_key",
            stripe_customer_id="cus_test",
            last_reported_usage_ts=prev_year,
            current_month_reported_units=100,
        )
        assert link_prev_year.needs_month_reset(now)
