"""Tests for YoroField and YoroWidget."""

import os

import django
import pytest

# Minimal Django settings for testing fields/widgets without a full project
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "tests._django_settings")

# Create minimal settings module
import types
import sys
_settings = types.ModuleType("tests._django_settings")
_settings.DATABASES = {"default": {"ENGINE": "django.db.backends.sqlite3", "NAME": ":memory:"}}
_settings.INSTALLED_APPS = ["django.contrib.contenttypes"]
_settings.USE_I18N = False
_settings.DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"
_settings.STATIC_URL = "/static/"
sys.modules["tests._django_settings"] = _settings
django.setup()

import yoro


class TestYoroFieldLogic:
    """Test the field's encoding/decoding logic without Django ORM."""

    def test_tuple_to_code(self):
        code = yoro.encode(5.345, -4.028, precision=12, domain="CI")
        assert code.startswith("CI-")
        assert len(code.split("-")[1]) == 5  # p=12 → 5 chars

    def test_roundtrip(self):
        code = yoro.encode(5.345, -4.028, precision=12, domain="CI")
        decoded = yoro.decode(code)
        assert abs(decoded["lat"] - 5.345) < 0.01
        assert abs(decoded["lon"] - (-4.028)) < 0.01

    def test_tuple_encode_various_domains(self):
        for domain in ["CI", "BF", "GH", "FR"]:
            dom = yoro.DOMAINS[domain]
            lat = (dom["lat_min"] + dom["lat_max"]) / 2
            lon = (dom["lon_min"] + dom["lon_max"]) / 2
            code = yoro.encode(lat, lon, domain=domain)
            assert code.startswith(f"{domain}-")

    def test_invalid_code_raises(self):
        with pytest.raises(ValueError):
            yoro.decode("INVALID")

    def test_empty_string_decode_raises(self):
        with pytest.raises(ValueError):
            yoro.decode("")


class TestYoroFieldDeconstruct:
    """Test that the field can be deconstructed for migrations."""

    def test_import_field(self):
        from yoro.django.fields import YoroField
        assert YoroField is not None

    def test_import_widget(self):
        from yoro.django.widgets import YoroWidget
        assert YoroWidget is not None

    def test_field_default_args(self):
        from yoro.django.fields import YoroField
        field = YoroField()
        assert field.yoro_domain == "CI"
        assert field.yoro_precision == 12
        assert field.max_length == 20

    def test_field_custom_args(self):
        from yoro.django.fields import YoroField
        field = YoroField(domain="BF", precision=14, map_height=400)
        assert field.yoro_domain == "BF"
        assert field.yoro_precision == 14
        assert field.yoro_map_height == 400

    def test_field_deconstruct_defaults(self):
        from yoro.django.fields import YoroField
        field = YoroField()
        field.set_attributes_from_name("address")
        _name, _path, _args, kwargs = field.deconstruct()
        # Default args should NOT appear in kwargs (clean migrations)
        assert "domain" not in kwargs
        assert "precision" not in kwargs

    def test_field_deconstruct_custom(self):
        from yoro.django.fields import YoroField
        field = YoroField(domain="BF", precision=19)
        field.set_attributes_from_name("address")
        _name, _path, _args, kwargs = field.deconstruct()
        assert kwargs["domain"] == "BF"
        assert kwargs["precision"] == 19

    def test_to_python_string(self):
        from yoro.django.fields import YoroField
        field = YoroField()
        assert field.to_python("CI-PV9XD") == "CI-PV9XD"

    def test_to_python_tuple(self):
        from yoro.django.fields import YoroField
        field = YoroField(domain="CI", precision=12)
        result = field.to_python((5.345, -4.028))
        assert result.startswith("CI-")
        assert isinstance(result, str)

    def test_to_python_list(self):
        from yoro.django.fields import YoroField
        field = YoroField(domain="CI")
        result = field.to_python([5.345, -4.028])
        assert result.startswith("CI-")

    def test_to_python_none(self):
        from yoro.django.fields import YoroField
        field = YoroField()
        assert field.to_python(None) == ""


class TestYoroWidget:
    """Test widget rendering."""

    def test_widget_media(self):
        from yoro.django.widgets import YoroWidget
        w = YoroWidget()
        css = str(w.media)
        assert "leaflet.css" in css
        assert "yoro-widget.css" in css
        assert "yoro-codec.min.js" in css
        assert "yoro-widget.js" in css

    def test_widget_context(self):
        from yoro.django.widgets import YoroWidget
        w = YoroWidget(domain="BF", precision=14, map_height=400)
        ctx = w.get_context("address", "BF-XXXXX", {"id": "id_address"})
        assert ctx["widget"]["domain"] == "BF"
        assert ctx["widget"]["precision"] == 14
        assert ctx["widget"]["map_height"] == 400

    def test_widget_custom_tiles(self):
        from yoro.django.widgets import YoroWidget
        url = "https://example.com/{z}/{x}/{y}.png"
        w = YoroWidget(tile_url=url)
        ctx = w.get_context("addr", "", {"id": "id_addr"})
        assert ctx["widget"]["tile_url"] == url
