"""
Tests for Themis forms.
"""
from django.contrib.auth import get_user_model
from django.test import TestCase

from themis.encryption import encrypt_value
from themis.forms import APIKeyCreateForm, APIKeyEditForm, ProfileSettingsForm
from themis.models import UserAPIKey

User = get_user_model()


class ProfileSettingsFormTest(TestCase):
    """Tests for ProfileSettingsForm."""

    def setUp(self):
        self.user = User.objects.create_user(username="formuser", password="pass123")
        self.profile = self.user.profile

    def test_valid_data(self):
        """Form is valid with correct data."""
        form = ProfileSettingsForm(
            data={
                "home_timezone": "America/Toronto",
                "current_timezone": "",
                "date_format": "DD/MM/YYYY",
                "time_format": "12-hour",
                "thousand_separator": "period",
                "week_start": "sunday",
                "theme_mode": "dark",
                "theme_name": "dracula",
                "dark_theme_name": "night",
                "notifications_enabled": True,
                "notifications_min_level": "info",
                "browser_notifications_enabled": False,
                "notification_retention_days": 30,
            },
            instance=self.profile,
        )
        self.assertTrue(form.is_valid())

    def test_save_updates_profile(self):
        """Saving the form updates the profile instance."""
        form = ProfileSettingsForm(
            data={
                "home_timezone": "Europe/London",
                "current_timezone": "",
                "date_format": "DD.MM.YYYY",
                "time_format": "12-hour",
                "thousand_separator": "space",
                "week_start": "saturday",
                "theme_mode": "light",
                "theme_name": "cupcake",
                "dark_theme_name": "halloween",
                "notifications_enabled": True,
                "notifications_min_level": "warning",
                "browser_notifications_enabled": True,
                "notification_retention_days": 60,
            },
            instance=self.profile,
        )
        self.assertTrue(form.is_valid())
        form.save()
        self.profile.refresh_from_db()
        self.assertEqual(self.profile.home_timezone, "Europe/London")
        self.assertEqual(self.profile.date_format, "DD.MM.YYYY")
        self.assertEqual(self.profile.theme_name, "cupcake")

    def test_invalid_timezone(self):
        """Form rejects invalid timezone values."""
        form = ProfileSettingsForm(
            data={
                "home_timezone": "Invalid/Timezone",
                "current_timezone": "",
                "date_format": "YYYY-MM-DD",
                "time_format": "24-hour",
                "thousand_separator": "comma",
                "week_start": "monday",
                "theme_mode": "auto",
                "theme_name": "corporate",
                "dark_theme_name": "business",
            },
            instance=self.profile,
        )
        self.assertFalse(form.is_valid())
        self.assertIn("home_timezone", form.errors)

    def test_correct_fields(self):
        """Form exposes the expected fields."""
        form = ProfileSettingsForm(instance=self.profile)
        expected_fields = {
            "home_timezone",
            "current_timezone",
            "date_format",
            "time_format",
            "thousand_separator",
            "week_start",
            "theme_mode",
            "theme_name",
            "dark_theme_name",
            "notifications_enabled",
            "notifications_min_level",
            "browser_notifications_enabled",
            "notification_retention_days",
        }
        self.assertEqual(set(form.fields.keys()), expected_fields)

    def test_widgets_have_daisyui_classes(self):
        """All widgets should have DaisyUI classes."""
        form = ProfileSettingsForm(instance=self.profile)
        for field_name, field in form.fields.items():
            css_class = field.widget.attrs.get("class", "")
            has_daisyui = any(
                kw in css_class
                for kw in ("select", "toggle", "input")
            )
            self.assertTrue(
                has_daisyui,
                f"{field_name} missing DaisyUI class (got: '{css_class}')",
            )


class APIKeyCreateFormTest(TestCase):
    """Tests for APIKeyCreateForm."""

    def test_valid_data(self):
        """Form is valid with required fields."""
        form = APIKeyCreateForm(
            data={
                "service_name": "OpenAI",
                "key_type": "api",
                "label": "Work",
                "key_value": "sk-abc123",
                "instructions": "Get from dashboard",
                "help_url": "https://platform.openai.com",
            }
        )
        self.assertTrue(form.is_valid())

    def test_valid_minimal_data(self):
        """Form is valid with only required fields."""
        form = APIKeyCreateForm(
            data={
                "service_name": "Test",
                "key_type": "api",
                "key_value": "my-key",
            }
        )
        self.assertTrue(form.is_valid())

    def test_missing_service_name(self):
        """Form requires service_name."""
        form = APIKeyCreateForm(
            data={
                "key_type": "api",
                "key_value": "my-key",
            }
        )
        self.assertFalse(form.is_valid())
        self.assertIn("service_name", form.errors)

    def test_missing_key_value(self):
        """Form requires key_value."""
        form = APIKeyCreateForm(
            data={
                "service_name": "Test",
                "key_type": "api",
            }
        )
        self.assertFalse(form.is_valid())
        self.assertIn("key_value", form.errors)

    def test_invalid_key_type(self):
        """Form rejects invalid key_type."""
        form = APIKeyCreateForm(
            data={
                "service_name": "Test",
                "key_type": "invalid_type",
                "key_value": "my-key",
            }
        )
        self.assertFalse(form.is_valid())
        self.assertIn("key_type", form.errors)

    def test_invalid_help_url(self):
        """Form rejects invalid URLs."""
        form = APIKeyCreateForm(
            data={
                "service_name": "Test",
                "key_type": "api",
                "key_value": "my-key",
                "help_url": "not-a-url",
            }
        )
        self.assertFalse(form.is_valid())
        self.assertIn("help_url", form.errors)

    def test_correct_fields(self):
        """Form has the expected fields."""
        form = APIKeyCreateForm()
        expected = {"service_name", "key_type", "label", "key_value", "instructions", "help_url"}
        self.assertEqual(set(form.fields.keys()), expected)


class APIKeyEditFormTest(TestCase):
    """Tests for APIKeyEditForm."""

    def setUp(self):
        self.user = User.objects.create_user(username="edituser", password="pass123")
        self.key = UserAPIKey.objects.create(
            user=self.user,
            service_name="OpenAI",
            key_type="api",
            encrypted_value=encrypt_value("sk-test"),
        )

    def test_valid_data(self):
        """Form is valid with correct data."""
        form = APIKeyEditForm(
            data={
                "service_name": "Anthropic",
                "key_type": "token",
                "label": "New Label",
                "instructions": "Updated instructions",
                "help_url": "https://docs.anthropic.com",
                "is_active": True,
            },
            instance=self.key,
        )
        self.assertTrue(form.is_valid())

    def test_no_key_value_field(self):
        """Edit form does not include key_value or encrypted_value."""
        form = APIKeyEditForm(instance=self.key)
        self.assertNotIn("key_value", form.fields)
        self.assertNotIn("encrypted_value", form.fields)

    def test_correct_fields(self):
        """Form exposes metadata fields only."""
        form = APIKeyEditForm(instance=self.key)
        expected = {"service_name", "key_type", "label", "instructions", "help_url", "is_active"}
        self.assertEqual(set(form.fields.keys()), expected)

    def test_save_updates_metadata(self):
        """Saving updates metadata without touching encrypted_value."""
        original_encrypted = self.key.encrypted_value
        form = APIKeyEditForm(
            data={
                "service_name": "Updated Service",
                "key_type": "token",
                "label": "Updated",
                "instructions": "",
                "help_url": "",
                "is_active": False,
            },
            instance=self.key,
        )
        self.assertTrue(form.is_valid())
        form.save()
        self.key.refresh_from_db()
        self.assertEqual(self.key.service_name, "Updated Service")
        self.assertEqual(self.key.key_type, "token")
        self.assertFalse(self.key.is_active)
        self.assertEqual(self.key.encrypted_value, original_encrypted)
