"""
Unit tests for identity/core/email_autoconfig.py

Tests email autoconfiguration views for various email clients.
"""

from unittest.mock import Mock, patch

import pytest
from django.test import RequestFactory

from smoothschedule.identity.core.email_autoconfig import (
    MozillaAutoconfigView,
    MicrosoftAutodiscoverView,
    AppleConfigProfileView,
    WellKnownAutoconfigView,
)


class TestMozillaAutoconfigView:
    """Tests for MozillaAutoconfigView."""

    def setup_method(self):
        self.factory = RequestFactory()
        self.view = MozillaAutoconfigView()

    def test_get_returns_xml_response(self):
        """Should return XML content type."""
        request = self.factory.get('/mail/config-v1.1.xml')

        response = self.view.get(request)

        assert response.status_code == 200
        assert 'application/xml' in response['Content-Type']

    def test_get_includes_email_provider_config(self):
        """Should include email provider configuration."""
        request = self.factory.get('/mail/config-v1.1.xml')

        response = self.view.get(request)
        content = response.content.decode('utf-8')

        assert '<emailProvider id="smoothschedule.com">' in content
        assert '<displayName>SmoothSchedule Mail</displayName>' in content

    def test_get_includes_imap_config(self):
        """Should include IMAP server configuration."""
        request = self.factory.get('/mail/config-v1.1.xml')

        response = self.view.get(request)
        content = response.content.decode('utf-8')

        assert '<incomingServer type="imap">' in content
        assert '<hostname>mail.talova.net</hostname>' in content
        assert '<port>993</port>' in content
        assert '<socketType>SSL</socketType>' in content

    def test_get_includes_smtp_config(self):
        """Should include SMTP server configuration."""
        request = self.factory.get('/mail/config-v1.1.xml')

        response = self.view.get(request)
        content = response.content.decode('utf-8')

        assert '<outgoingServer type="smtp">' in content
        assert '<port>587</port>' in content
        assert '<socketType>STARTTLS</socketType>' in content

    def test_get_uses_email_placeholder_without_param(self):
        """Should use placeholder when no email provided."""
        request = self.factory.get('/mail/config-v1.1.xml')

        response = self.view.get(request)
        content = response.content.decode('utf-8')

        assert '%EMAILADDRESS%' in content

    def test_get_with_email_parameter(self):
        """Should accept email parameter."""
        request = self.factory.get('/mail/config-v1.1.xml?emailaddress=user@smoothschedule.com')

        response = self.view.get(request)
        content = response.content.decode('utf-8')

        assert response.status_code == 200
        # The template uses %EMAILADDRESS% placeholder regardless
        assert '%EMAILADDRESS%' in content

    def test_get_extracts_local_part_from_email(self):
        """Should extract local part when email contains @."""
        request = self.factory.get('/mail/config-v1.1.xml?emailaddress=testuser@domain.com')

        # The view extracts local_part but uses placeholders in output
        response = self.view.get(request)

        assert response.status_code == 200


class TestMicrosoftAutodiscoverView:
    """Tests for MicrosoftAutodiscoverView."""

    def setup_method(self):
        self.factory = RequestFactory()
        self.view = MicrosoftAutodiscoverView()

    def test_post_returns_xml_response(self):
        """Should return XML content type for POST."""
        request = self.factory.post('/autodiscover/autodiscover.xml')

        response = self.view.post(request)

        assert response.status_code == 200
        assert 'application/xml' in response['Content-Type']

    def test_post_includes_autodiscover_schema(self):
        """Should include Microsoft Autodiscover schema."""
        request = self.factory.post('/autodiscover/autodiscover.xml')

        response = self.view.post(request)
        content = response.content.decode('utf-8')

        assert 'schemas.microsoft.com/exchange/autodiscover' in content
        assert '<Autodiscover' in content

    def test_post_includes_imap_protocol(self):
        """Should include IMAP protocol configuration."""
        request = self.factory.post('/autodiscover/autodiscover.xml')

        response = self.view.post(request)
        content = response.content.decode('utf-8')

        assert '<Type>IMAP</Type>' in content
        assert '<Server>mail.talova.net</Server>' in content
        assert '<Port>993</Port>' in content

    def test_post_includes_smtp_protocol(self):
        """Should include SMTP protocol configuration."""
        request = self.factory.post('/autodiscover/autodiscover.xml')

        response = self.view.post(request)
        content = response.content.decode('utf-8')

        assert '<Type>SMTP</Type>' in content
        assert '<Port>587</Port>' in content
        assert '<Encryption>TLS</Encryption>' in content

    def test_get_delegates_to_post(self):
        """GET should delegate to POST handler."""
        request = self.factory.get('/autodiscover/autodiscover.xml')

        response = self.view.get(request)

        assert response.status_code == 200
        assert 'application/xml' in response['Content-Type']


class TestAppleConfigProfileView:
    """Tests for AppleConfigProfileView."""

    def setup_method(self):
        self.factory = RequestFactory()
        self.view = AppleConfigProfileView()

    def test_get_requires_email_parameter(self):
        """Should return 400 when email parameter is missing."""
        request = self.factory.get('/email/apple-profile.mobileconfig')

        response = self.view.get(request)

        assert response.status_code == 400
        assert 'Email parameter required' in response.content.decode('utf-8')

    def test_get_requires_valid_email_format(self):
        """Should return 400 when email has no @ symbol."""
        request = self.factory.get('/email/apple-profile.mobileconfig?email=invalid')

        response = self.view.get(request)

        assert response.status_code == 400

    def test_get_returns_mobileconfig_content_type(self):
        """Should return Apple configuration profile content type."""
        request = self.factory.get('/email/apple-profile.mobileconfig?email=user@smoothschedule.com')

        response = self.view.get(request)

        assert response.status_code == 200
        assert 'application/x-apple-aspen-config' in response['Content-Type']

    def test_get_includes_content_disposition(self):
        """Should include Content-Disposition header for download."""
        request = self.factory.get('/email/apple-profile.mobileconfig?email=user@smoothschedule.com')

        response = self.view.get(request)

        assert 'Content-Disposition' in response
        assert 'attachment' in response['Content-Disposition']
        assert '.mobileconfig' in response['Content-Disposition']

    def test_get_includes_plist_structure(self):
        """Should return valid plist XML structure."""
        request = self.factory.get('/email/apple-profile.mobileconfig?email=user@smoothschedule.com')

        response = self.view.get(request)
        content = response.content.decode('utf-8')

        assert '<?xml version="1.0"' in content
        assert '<!DOCTYPE plist' in content
        assert '<plist version="1.0">' in content

    def test_get_includes_email_account_config(self):
        """Should include email account configuration."""
        request = self.factory.get('/email/apple-profile.mobileconfig?email=user@smoothschedule.com')

        response = self.view.get(request)
        content = response.content.decode('utf-8')

        assert '<key>EmailAccountType</key>' in content
        assert '<string>EmailTypeIMAP</string>' in content
        assert '<key>EmailAddress</key>' in content
        assert 'user@smoothschedule.com' in content

    def test_get_includes_imap_settings(self):
        """Should include IMAP server settings."""
        request = self.factory.get('/email/apple-profile.mobileconfig?email=user@smoothschedule.com')

        response = self.view.get(request)
        content = response.content.decode('utf-8')

        assert '<key>IncomingMailServerHostName</key>' in content
        assert '<string>mail.talova.net</string>' in content
        assert '<key>IncomingMailServerPortNumber</key>' in content
        assert '<integer>993</integer>' in content

    def test_get_includes_smtp_settings(self):
        """Should include SMTP server settings."""
        request = self.factory.get('/email/apple-profile.mobileconfig?email=user@smoothschedule.com')

        response = self.view.get(request)
        content = response.content.decode('utf-8')

        assert '<key>OutgoingMailServerHostName</key>' in content
        assert '<string>mail.talova.net</string>' in content
        assert '<key>OutgoingMailServerPortNumber</key>' in content
        assert '<integer>587</integer>' in content

    def test_get_generates_unique_uuids(self):
        """Should generate unique UUIDs for profile."""
        request = self.factory.get('/email/apple-profile.mobileconfig?email=user@smoothschedule.com')

        response = self.view.get(request)
        content = response.content.decode('utf-8')

        assert '<key>PayloadUUID</key>' in content
        # UUIDs should be uppercase
        assert content.count('<key>PayloadUUID</key>') >= 2

    def test_get_creates_display_name_from_email(self):
        """Should create display name from email local part."""
        request = self.factory.get('/email/apple-profile.mobileconfig?email=john.doe@smoothschedule.com')

        response = self.view.get(request)
        content = response.content.decode('utf-8')

        # john.doe should become "John Doe"
        assert '<key>EmailAccountName</key>' in content
        assert 'John Doe' in content


class TestWellKnownAutoconfigView:
    """Tests for WellKnownAutoconfigView."""

    def setup_method(self):
        self.factory = RequestFactory()
        self.view = WellKnownAutoconfigView()

    def test_get_redirects_to_mail_config(self):
        """Should redirect to /mail/config-v1.1.xml."""
        request = self.factory.get('/.well-known/autoconfig/mail/config-v1.1.xml')

        response = self.view.get(request)

        assert response.status_code == 302
        assert '/mail/config-v1.1.xml' in response.url

    def test_get_preserves_email_parameter(self):
        """Should preserve emailaddress parameter in redirect."""
        request = self.factory.get('/.well-known/autoconfig/mail/config-v1.1.xml?emailaddress=test@example.com')

        response = self.view.get(request)

        assert response.status_code == 302
        assert 'emailaddress=test@example.com' in response.url

    def test_get_without_email_parameter(self):
        """Should redirect without email param when not provided."""
        request = self.factory.get('/.well-known/autoconfig/mail/config-v1.1.xml')

        response = self.view.get(request)

        assert response.status_code == 302
        assert response.url == '/mail/config-v1.1.xml'
