"""Tests for PI FYAD models."""

from datetime import timedelta

from django.test import TestCase
from django.utils import timezone

from allianceauth.eveonline.models import EveCharacter

from aa_pi_fyad.constants import (
    EXTRACTOR_STATUS_ACTIVE,
    EXTRACTOR_STATUS_EXPIRED,
    EXTRACTOR_STATUS_IDLE,
)
from aa_pi_fyad.models import (
    CharacterOwner,
    CharacterPlanet,
    PlanetPin,
    PlanetTemplate,
    StorageContents,
)


class TestPlanetPin(TestCase):
    """Tests for PlanetPin model."""

    @classmethod
    def setUpTestData(cls):
        """Create shared test data."""
        cls.character = EveCharacter.objects.create(
            character_id=90000001,
            character_name="Test Pilot",
            corporation_id=98000001,
            corporation_name="Test Corp",
        )
        cls.owner = CharacterOwner.objects.create(character=cls.character)
        cls.planet = CharacterPlanet.objects.create(
            owner=cls.owner,
            planet_id=40000001,
            planet_type_id=2014,
            planet_name="Test III",
            solar_system_id=30000001,
            solar_system_name="Test System",
        )

    def _make_extractor(self, install_time=None, expiry_time=None):
        """Create an extractor pin."""
        return PlanetPin.objects.create(
            planet=self.planet,
            pin_id=1000000 + PlanetPin.objects.count(),
            type_id=2848,
            type_name="Extractor Control Unit",
            is_extractor=True,
            install_time=install_time,
            expiry_time=expiry_time,
        )

    def test_extractor_active(self):
        """Active extractor has future expiry and install time."""
        now = timezone.now()
        pin = self._make_extractor(
            install_time=now - timedelta(hours=1),
            expiry_time=now + timedelta(hours=23),
        )
        self.assertEqual(pin.extractor_status, EXTRACTOR_STATUS_ACTIVE)
        self.assertIsNotNone(pin.time_remaining)
        self.assertGreater(pin.time_remaining.total_seconds(), 0)

    def test_extractor_expired(self):
        """Expired extractor has past expiry."""
        now = timezone.now()
        pin = self._make_extractor(
            install_time=now - timedelta(days=2),
            expiry_time=now - timedelta(hours=1),
        )
        self.assertEqual(pin.extractor_status, EXTRACTOR_STATUS_EXPIRED)
        self.assertIsNone(pin.time_remaining)

    def test_extractor_idle(self):
        """Idle extractor has no expiry time set."""
        pin = self._make_extractor()
        self.assertEqual(pin.extractor_status, EXTRACTOR_STATUS_IDLE)
        self.assertIsNone(pin.time_remaining)

    def test_eve_image_url(self):
        """EVE image URL is constructed correctly."""
        pin = self._make_extractor()
        self.assertIn("/types/2848/icon", pin.eve_image_url)
        self.assertIn("size=64", pin.eve_image_url)

    def test_storage_fill_calculation(self):
        """Storage fill percentage calculates correctly."""
        pin = PlanetPin.objects.create(
            planet=self.planet,
            pin_id=2000001,
            type_id=2256,
            type_name="Storage Facility",
            is_storage=True,
            storage_used_m3=6000.0,
        )
        pin.update_storage_capacity()
        self.assertEqual(pin.storage_capacity_m3, 12000.0)
        self.assertAlmostEqual(pin.storage_fill_pct, 50.0)

    def test_storage_fill_zero_capacity(self):
        """Zero capacity doesn't cause division error."""
        pin = PlanetPin.objects.create(
            planet=self.planet,
            pin_id=2000002,
            type_id=99999,
            type_name="Unknown Storage",
            is_storage=True,
            storage_used_m3=100.0,
        )
        pin.update_storage_capacity()
        self.assertEqual(pin.storage_capacity_m3, 0.0)
        self.assertEqual(pin.storage_fill_pct, 0.0)


class TestStorageContents(TestCase):
    """Tests for StorageContents model."""

    @classmethod
    def setUpTestData(cls):
        character = EveCharacter.objects.create(
            character_id=90000002,
            character_name="Storage Pilot",
            corporation_id=98000001,
            corporation_name="Test Corp",
        )
        owner = CharacterOwner.objects.create(character=character)
        planet = CharacterPlanet.objects.create(
            owner=owner,
            planet_id=40000002,
            planet_type_id=2015,
            planet_name="Ice IV",
            solar_system_id=30000002,
            solar_system_name="Ice System",
        )
        cls.pin = PlanetPin.objects.create(
            planet=planet,
            pin_id=3000001,
            type_id=2256,
            type_name="Storage Facility",
            is_storage=True,
        )

    def test_contents_creation(self):
        """Storage contents are created and ordered by volume."""
        StorageContents.objects.create(
            pin=self.pin,
            type_id=2389,
            type_name="Plasmoids",
            quantity=1000,
            volume_per_unit=0.38,
            total_volume=380.0,
        )
        StorageContents.objects.create(
            pin=self.pin,
            type_id=2390,
            type_name="Electrolytes",
            quantity=500,
            volume_per_unit=0.38,
            total_volume=190.0,
        )
        contents = StorageContents.objects.filter(pin=self.pin)
        self.assertEqual(contents.count(), 2)
        # Ordered by -total_volume
        self.assertEqual(contents.first().type_name, "Plasmoids")

    def test_eve_image_url(self):
        """Storage content image URL uses size 32."""
        item = StorageContents.objects.create(
            pin=self.pin,
            type_id=2389,
            type_name="Plasmoids",
            quantity=100,
        )
        self.assertIn("/types/2389/icon", item.eve_image_url)
        self.assertIn("size=32", item.eve_image_url)


class TestCharacterPlanet(TestCase):
    """Tests for CharacterPlanet model."""

    @classmethod
    def setUpTestData(cls):
        cls.character = EveCharacter.objects.create(
            character_id=90000003,
            character_name="Planet Pilot",
            corporation_id=98000001,
            corporation_name="Test Corp",
        )
        cls.owner = CharacterOwner.objects.create(character=cls.character)
        cls.planet = CharacterPlanet.objects.create(
            owner=cls.owner,
            planet_id=40000003,
            planet_type_id=2016,
            planet_name="Gas V",
            solar_system_id=30000003,
            solar_system_name="Gas System",
        )

    def test_extractor_summary(self):
        """Extractor summary returns correct counts."""
        now = timezone.now()
        # Active
        PlanetPin.objects.create(
            planet=self.planet, pin_id=4000001, type_id=2848,
            is_extractor=True,
            install_time=now - timedelta(hours=1),
            expiry_time=now + timedelta(hours=23),
        )
        # Expired
        PlanetPin.objects.create(
            planet=self.planet, pin_id=4000002, type_id=2848,
            is_extractor=True,
            install_time=now - timedelta(days=2),
            expiry_time=now - timedelta(hours=1),
        )
        # Idle
        PlanetPin.objects.create(
            planet=self.planet, pin_id=4000003, type_id=2848,
            is_extractor=True,
        )

        summary = self.planet.extractor_summary
        self.assertEqual(summary["active"], 1)
        self.assertEqual(summary["expired"], 1)
        self.assertEqual(summary["idle"], 1)

    def test_str(self):
        """String representation includes character and planet name."""
        self.assertIn("Planet Pilot", str(self.planet))
        self.assertIn("Gas V", str(self.planet))


class TestPlanetTemplate(TestCase):
    """Tests for PlanetTemplate model."""

    def test_template_creation(self):
        """Templates can be created with all fields."""
        template = PlanetTemplate.objects.create(
            name="P1 Factory Planet",
            description="Basic P1 extractor setup",
            planet_type_id=2014,
            planet_type_name="Temperate",
            visibility="corp",
            template_data={"pins": [], "links": [], "routes": []},
            pin_count=8,
            factory_count=4,
            extractor_count=2,
            output_products=["Reactive Metals", "Biofuels"],
        )
        self.assertEqual(str(template), "Template: P1 Factory Planet (Temperate)")
        self.assertEqual(template.output_products, ["Reactive Metals", "Biofuels"])
