"""
Unit tests for scheduling/schedule/api_views.py

Tests sandbox mode, business CRUD, and OAuth API endpoints.
"""
from unittest.mock import Mock, patch, MagicMock
from rest_framework.test import APIRequestFactory
from rest_framework import status
import pytest


class TestSandboxStatusView:
    """Tests for sandbox_status_view."""

    def test_returns_disabled_when_no_tenant(self):
        """Should return sandbox disabled when user has no tenant."""
        from smoothschedule.scheduling.schedule.api_views import sandbox_status_view

        factory = APIRequestFactory()
        request = factory.get('/api/sandbox/status/')
        request.user = Mock()
        request.user.tenant = None

        response = sandbox_status_view(request)

        assert response.status_code == status.HTTP_200_OK
        assert response.data['sandbox_mode'] is False
        assert response.data['sandbox_enabled'] is False
        assert response.data['sandbox_schema'] is None

    def test_returns_status_when_tenant_exists(self):
        """Should return sandbox status when tenant exists."""
        from smoothschedule.scheduling.schedule.api_views import sandbox_status_view

        factory = APIRequestFactory()
        request = factory.get('/api/sandbox/status/')
        request.user = Mock()
        request.user.tenant = Mock(
            sandbox_enabled=True,
            sandbox_schema_name='demo_sandbox'
        )
        request.session = {'sandbox_mode': True}

        response = sandbox_status_view(request)

        assert response.status_code == status.HTTP_200_OK
        assert response.data['sandbox_mode'] is True
        assert response.data['sandbox_enabled'] is True
        assert response.data['sandbox_schema'] == 'demo_sandbox'

    def test_returns_no_schema_when_sandbox_disabled(self):
        """Should not return schema when sandbox is disabled."""
        from smoothschedule.scheduling.schedule.api_views import sandbox_status_view

        factory = APIRequestFactory()
        request = factory.get('/api/sandbox/status/')
        request.user = Mock()
        request.user.tenant = Mock(
            sandbox_enabled=False,
            sandbox_schema_name='demo_sandbox'
        )
        request.session = {}

        response = sandbox_status_view(request)

        assert response.status_code == status.HTTP_200_OK
        assert response.data['sandbox_schema'] is None


class TestSandboxToggleView:
    """Tests for sandbox_toggle_view."""

    def test_returns_403_when_no_tenant(self):
        """Should return 403 when user has no tenant."""
        from smoothschedule.scheduling.schedule.api_views import sandbox_toggle_view

        factory = APIRequestFactory()
        request = factory.post('/api/sandbox/toggle/', {'sandbox': True}, format='json')
        request.user = Mock()
        request.user.tenant = None
        request.data = {'sandbox': True}

        response = sandbox_toggle_view(request)

        assert response.status_code == status.HTTP_403_FORBIDDEN
        assert 'No business' in response.data['error']

    def test_returns_403_when_sandbox_not_enabled(self):
        """Should return 403 when sandbox not enabled for tenant."""
        from smoothschedule.scheduling.schedule.api_views import sandbox_toggle_view

        factory = APIRequestFactory()
        request = factory.post('/api/sandbox/toggle/', {'sandbox': True}, format='json')
        request.user = Mock()
        request.user.tenant = Mock(sandbox_enabled=False)
        request.data = {'sandbox': True}

        response = sandbox_toggle_view(request)

        assert response.status_code == status.HTTP_403_FORBIDDEN
        assert 'not enabled' in response.data['error']

    def test_returns_400_when_schema_not_configured(self):
        """Should return 400 when sandbox schema not configured."""
        from smoothschedule.scheduling.schedule.api_views import sandbox_toggle_view

        factory = APIRequestFactory()
        request = factory.post('/api/sandbox/toggle/', {'sandbox': True}, format='json')
        request.user = Mock()
        request.user.tenant = Mock(
            sandbox_enabled=True,
            sandbox_schema_name=None
        )
        request.data = {'sandbox': True}

        response = sandbox_toggle_view(request)

        assert response.status_code == status.HTTP_400_BAD_REQUEST
        assert 'not configured' in response.data['error']

    def test_enables_sandbox_mode(self):
        """Should enable sandbox mode and store in session."""
        from smoothschedule.scheduling.schedule.api_views import sandbox_toggle_view

        factory = APIRequestFactory()
        request = factory.post('/api/sandbox/toggle/', {'sandbox': True}, format='json')
        request.user = Mock()
        request.user.tenant = Mock(
            sandbox_enabled=True,
            sandbox_schema_name='demo_sandbox'
        )
        request.data = {'sandbox': True}
        # Mock session as a dict-like object
        request.session = {}

        response = sandbox_toggle_view(request)

        assert response.status_code == status.HTTP_200_OK
        assert response.data['sandbox_mode'] is True
        assert 'Test' in response.data['message']

    def test_disables_sandbox_mode(self):
        """Should disable sandbox mode."""
        from smoothschedule.scheduling.schedule.api_views import sandbox_toggle_view

        factory = APIRequestFactory()
        request = factory.post('/api/sandbox/toggle/', {'sandbox': False}, format='json')
        request.user = Mock()
        request.user.tenant = Mock(
            sandbox_enabled=True,
            sandbox_schema_name='demo_sandbox'
        )
        request.data = {'sandbox': False}
        request.session = {'sandbox_mode': True}

        response = sandbox_toggle_view(request)

        assert response.status_code == status.HTTP_200_OK
        assert response.data['sandbox_mode'] is False
        assert 'Live' in response.data['message']


class TestSandboxResetView:
    """Tests for sandbox_reset_view."""

    def test_returns_403_when_no_tenant(self):
        """Should return 403 when user has no tenant."""
        from smoothschedule.scheduling.schedule.api_views import sandbox_reset_view

        factory = APIRequestFactory()
        request = factory.post('/api/sandbox/reset/', {})
        request.user = Mock()
        request.user.tenant = None

        response = sandbox_reset_view(request)

        assert response.status_code == status.HTTP_403_FORBIDDEN
        assert 'No business' in response.data['error']

    def test_returns_403_when_user_not_owner(self):
        """Should return 403 when user is not owner."""
        from smoothschedule.scheduling.schedule.api_views import sandbox_reset_view

        factory = APIRequestFactory()
        request = factory.post('/api/sandbox/reset/', {})
        request.user = Mock()
        request.user.tenant = Mock(sandbox_enabled=True)
        request.user.role = 'TENANT_STAFF'

        response = sandbox_reset_view(request)

        assert response.status_code == status.HTTP_403_FORBIDDEN
        assert 'Only business owners' in response.data['error']

    def test_returns_403_when_sandbox_not_available(self):
        """Should return 403 when sandbox not available."""
        from smoothschedule.scheduling.schedule.api_views import sandbox_reset_view

        factory = APIRequestFactory()
        request = factory.post('/api/sandbox/reset/', {})
        request.user = Mock()
        request.user.tenant = Mock(
            sandbox_enabled=False,
            sandbox_schema_name=None
        )
        request.user.role = 'TENANT_OWNER'

        response = sandbox_reset_view(request)

        assert response.status_code == status.HTTP_403_FORBIDDEN
        assert 'not available' in response.data['error']

    def test_resets_sandbox_for_owner(self):
        """Should reset sandbox for owner."""
        from smoothschedule.scheduling.schedule.api_views import sandbox_reset_view

        factory = APIRequestFactory()
        request = factory.post('/api/sandbox/reset/', {})
        request.user = Mock()
        request.user.tenant = Mock(
            sandbox_enabled=True,
            sandbox_schema_name='demo_sandbox'
        )
        request.user.role = 'TENANT_OWNER'

        response = sandbox_reset_view(request)

        assert response.status_code == status.HTTP_200_OK
        assert 'reset successfully' in response.data['message']


class TestCurrentBusinessView:
    """Tests for current_business_view."""

    def test_returns_null_for_platform_users(self):
        """Should return null for users without tenant."""
        from smoothschedule.scheduling.schedule.api_views import current_business_view

        factory = APIRequestFactory()
        request = factory.get('/api/business/current/')
        request.user = Mock()
        request.user.tenant = None

        response = current_business_view(request)

        assert response.status_code == status.HTTP_200_OK
        assert response.data is None

    def test_returns_business_data(self):
        """Should return business data for tenant users."""
        from smoothschedule.scheduling.schedule.api_views import current_business_view

        factory = APIRequestFactory()
        request = factory.get('/api/business/current/')
        request.build_absolute_uri = Mock(return_value='http://example.com/logo.png')

        # Create mock tenant
        mock_domain = Mock()
        mock_domain.domain = 'demo.lvh.me'
        mock_domain.is_primary = True

        mock_tenant = Mock()
        mock_tenant.id = 1
        mock_tenant.name = 'Demo Business'
        mock_tenant.schema_name = 'demo'
        mock_tenant.is_active = True
        mock_tenant.created_on = Mock()
        mock_tenant.created_on.isoformat.return_value = '2024-01-01T00:00:00'
        mock_tenant.primary_color = '#3b82f6'
        mock_tenant.secondary_color = '#10b981'
        mock_tenant.logo = None
        mock_tenant.email_logo = None
        mock_tenant.logo_display_mode = 'full'
        mock_tenant.timezone = 'America/New_York'
        mock_tenant.timezone_display_mode = 'business'
        mock_tenant.booking_return_url = ''
        mock_tenant.service_selection_heading = 'Choose'
        mock_tenant.service_selection_subheading = 'Select'
        mock_tenant.payment_mode = 'stripe'
        mock_tenant.domains.filter.return_value.first.return_value = mock_domain

        # Mock billing subscription (plan is "pro")
        mock_plan = Mock()
        mock_plan.code = 'pro'
        mock_plan_version = Mock()
        mock_plan_version.plan = mock_plan
        mock_subscription = Mock()
        mock_subscription.plan_version = mock_plan_version
        mock_tenant.billing_subscription = mock_subscription

        # Mock has_feature to return correct values for billing feature codes
        def has_feature_impl(feature_code):
            feature_map = {
                'sms_enabled': True,
                'integrations_enabled': False,
                'api_access': False,
                'custom_domain': False,
                'white_label': False,
                'can_manage_oauth': False,
                'can_use_automations': True,
                'can_create_automations': False,
                'can_use_tasks': True,
                'can_export_data': False,
                'can_add_video_conferencing': False,
                'team_permissions': False,
                'masked_calling_enabled': False,
                'can_use_pos': False,
                'mobile_app_access': True,
                'can_use_contracts': False,
                'multi_location': False,
            }
            return feature_map.get(feature_code, False)

        mock_tenant.has_feature = Mock(side_effect=has_feature_impl)

        request.user = Mock()
        request.user.tenant = mock_tenant

        response = current_business_view(request)

        assert response.status_code == status.HTTP_200_OK
        assert response.data['id'] == 1
        assert response.data['name'] == 'Demo Business'
        assert response.data['subdomain'] == 'demo'
        assert response.data['plan'] == 'pro'
        assert response.data['plan_permissions']['sms_reminders'] is True
        assert response.data['plan_permissions']['automations'] is True


class TestUpdateBusinessView:
    """Tests for update_business_view."""

    def test_returns_404_when_no_tenant(self):
        """Should return 404 when user has no tenant."""
        from smoothschedule.scheduling.schedule.api_views import update_business_view

        factory = APIRequestFactory()
        request = factory.patch('/api/business/current/update/', {})
        request.user = Mock()
        request.user.tenant = None

        response = update_business_view(request)

        assert response.status_code == status.HTTP_404_NOT_FOUND
        assert 'No business' in response.data['error']

    def test_returns_403_when_user_not_owner(self):
        """Should return 403 when user is not owner."""
        from smoothschedule.scheduling.schedule.api_views import update_business_view

        factory = APIRequestFactory()
        request = factory.patch('/api/business/current/update/', {})
        request.user = Mock()
        request.user.tenant = Mock()
        request.user.role = 'TENANT_STAFF'

        response = update_business_view(request)

        assert response.status_code == status.HTTP_403_FORBIDDEN
        assert 'Only business owners' in response.data['error']

    def test_updates_name(self):
        """Should update business name."""
        from smoothschedule.scheduling.schedule.api_views import update_business_view

        factory = APIRequestFactory()
        request = factory.patch('/api/business/current/update/', {'name': 'New Name'})
        request.data = {'name': 'New Name'}
        request.build_absolute_uri = Mock(return_value='http://example.com/logo.png')

        mock_tenant = Mock()
        mock_tenant.name = 'Old Name'
        mock_tenant.logo = None
        mock_tenant.email_logo = None
        mock_tenant.id = 1
        mock_tenant.is_active = True
        mock_tenant.created_on = Mock()
        mock_tenant.created_on.isoformat.return_value = '2024-01-01'
        mock_tenant.subscription_tier = 'FREE'
        mock_tenant.subscription_plan = None
        mock_tenant.schema_name = 'test'
        mock_tenant.primary_color = '#000'
        mock_tenant.secondary_color = '#fff'
        mock_tenant.logo_display_mode = 'full'
        mock_tenant.timezone = 'UTC'
        mock_tenant.timezone_display_mode = 'business'
        mock_tenant.booking_return_url = ''
        mock_tenant.service_selection_heading = ''
        mock_tenant.service_selection_subheading = ''
        mock_tenant.can_use_sms_reminders = False
        mock_tenant.can_use_webhooks = False
        mock_tenant.can_api_access = False
        mock_tenant.can_use_custom_domain = False
        mock_tenant.can_white_label = False
        mock_tenant.can_manage_oauth_credentials = False
        mock_tenant.can_use_automations = False
        mock_tenant.can_create_automations = False
        mock_tenant.can_use_tasks = False
        mock_tenant.can_export_data = False
        mock_tenant.can_add_video_conferencing = False
        mock_tenant.can_require_2fa = False
        mock_tenant.can_use_masked_phone_numbers = False
        mock_tenant.can_use_pos = False
        mock_tenant.can_use_mobile_app = False
        mock_tenant.can_use_contracts = False
        mock_tenant.payment_mode = 'none'
        mock_tenant.domains.filter.return_value.first.return_value = None

        request.user = Mock()
        request.user.tenant = mock_tenant
        request.user.role = 'TENANT_OWNER'

        response = update_business_view(request)

        assert response.status_code == status.HTTP_200_OK
        assert mock_tenant.name == 'New Name'
        mock_tenant.save.assert_called_once()

    def test_updates_colors(self):
        """Should update primary and secondary colors."""
        from smoothschedule.scheduling.schedule.api_views import update_business_view

        factory = APIRequestFactory()
        request = factory.patch('/api/business/current/update/', {
            'primary_color': '#ff0000',
            'secondary_color': '#00ff00'
        })
        request.data = {
            'primary_color': '#ff0000',
            'secondary_color': '#00ff00'
        }
        request.build_absolute_uri = Mock(return_value='http://example.com')

        mock_tenant = Mock()
        mock_tenant.id = 1
        mock_tenant.name = 'Test'
        mock_tenant.logo = None
        mock_tenant.email_logo = None
        mock_tenant.primary_color = '#000'
        mock_tenant.secondary_color = '#fff'
        mock_tenant.is_active = True
        mock_tenant.created_on = Mock()
        mock_tenant.created_on.isoformat.return_value = '2024-01-01'
        mock_tenant.subscription_tier = 'FREE'
        mock_tenant.subscription_plan = None
        mock_tenant.schema_name = 'test'
        mock_tenant.logo_display_mode = 'full'
        mock_tenant.timezone = 'UTC'
        mock_tenant.timezone_display_mode = 'business'
        mock_tenant.booking_return_url = ''
        mock_tenant.service_selection_heading = ''
        mock_tenant.service_selection_subheading = ''
        mock_tenant.can_use_sms_reminders = False
        mock_tenant.can_use_webhooks = False
        mock_tenant.can_api_access = False
        mock_tenant.can_use_custom_domain = False
        mock_tenant.can_white_label = False
        mock_tenant.can_manage_oauth_credentials = False
        mock_tenant.can_use_automations = False
        mock_tenant.can_create_automations = False
        mock_tenant.can_use_tasks = False
        mock_tenant.can_export_data = False
        mock_tenant.can_add_video_conferencing = False
        mock_tenant.can_require_2fa = False
        mock_tenant.can_use_masked_phone_numbers = False
        mock_tenant.can_use_pos = False
        mock_tenant.can_use_mobile_app = False
        mock_tenant.can_use_contracts = False
        mock_tenant.payment_mode = 'none'
        mock_tenant.domains.filter.return_value.first.return_value = None

        request.user = Mock()
        request.user.tenant = mock_tenant
        request.user.role = 'TENANT_OWNER'

        response = update_business_view(request)

        assert response.status_code == status.HTTP_200_OK
        assert mock_tenant.primary_color == '#ff0000'
        assert mock_tenant.secondary_color == '#00ff00'


class TestOAuthSettingsView:
    """Tests for oauth_settings_view."""

    def test_get_returns_404_without_tenant(self):
        """Should return 404 when user has no tenant."""
        from smoothschedule.scheduling.schedule.api_views import oauth_settings_view

        factory = APIRequestFactory()
        request = factory.get('/api/oauth/settings/')
        request.user = Mock()
        request.user.tenant = None

        response = oauth_settings_view(request)

        assert response.status_code == status.HTTP_404_NOT_FOUND
        assert 'No business' in response.data['error']

    def test_get_returns_settings(self):
        """Should return oauth settings for tenant."""
        from smoothschedule.scheduling.schedule.api_views import oauth_settings_view

        factory = APIRequestFactory()
        request = factory.get('/api/oauth/settings/')

        mock_tenant = Mock()
        mock_tenant.oauth_enabled_providers = ['google']
        mock_tenant.oauth_allow_registration = True
        mock_tenant.oauth_auto_link_by_email = True
        mock_tenant.oauth_use_custom_credentials = False

        request.user = Mock()
        request.user.tenant = mock_tenant

        response = oauth_settings_view(request)

        assert response.status_code == status.HTTP_200_OK
        assert response.data['settings']['enabled_providers'] == ['google']
        assert 'available_providers' in response.data

    def test_patch_returns_403_when_not_owner(self):
        """Should return 403 when user is not owner on PATCH."""
        from smoothschedule.scheduling.schedule.api_views import oauth_settings_view

        factory = APIRequestFactory()
        request = factory.patch('/api/oauth/settings/', {})
        request.data = {}

        mock_tenant = Mock()
        request.user = Mock()
        request.user.tenant = mock_tenant
        request.user.role = 'tenant_staff'

        response = oauth_settings_view(request)

        assert response.status_code == status.HTTP_403_FORBIDDEN
        assert 'Only business owners' in response.data['error']


class TestCustomDomainsView:
    """Tests for custom_domains_view."""

    def test_get_returns_404_without_tenant(self):
        """Should return 404 when user has no tenant."""
        from smoothschedule.scheduling.schedule.api_views import custom_domains_view

        factory = APIRequestFactory()
        request = factory.get('/api/custom-domains/')
        request.user = Mock()
        request.user.tenant = None

        response = custom_domains_view(request)

        assert response.status_code == status.HTTP_404_NOT_FOUND
        assert 'No business' in response.data['error']

    def test_get_returns_403_when_not_owner(self):
        """Should return 403 when user is not owner."""
        from smoothschedule.scheduling.schedule.api_views import custom_domains_view

        factory = APIRequestFactory()
        request = factory.get('/api/custom-domains/')
        request.user = Mock()
        request.user.tenant = Mock()
        request.user.role = 'tenant_staff'

        response = custom_domains_view(request)

        assert response.status_code == status.HTTP_403_FORBIDDEN
        assert 'Only business owners' in response.data['error']



class TestCustomDomainDetailView:
    """Tests for custom_domain_detail_view."""

    def test_returns_404_without_tenant(self):
        """Should return 404 when user has no tenant."""
        from smoothschedule.scheduling.schedule.api_views import custom_domain_detail_view

        factory = APIRequestFactory()
        request = factory.get('/api/custom-domains/1/')
        request.user = Mock()
        request.user.tenant = None

        response = custom_domain_detail_view(request, domain_id=1)

        assert response.status_code == status.HTTP_404_NOT_FOUND
        assert 'No business' in response.data['error']

    def test_returns_403_when_not_owner(self):
        """Should return 403 when user is not owner."""
        from smoothschedule.scheduling.schedule.api_views import custom_domain_detail_view

        factory = APIRequestFactory()
        request = factory.get('/api/custom-domains/1/')
        request.user = Mock()
        request.user.tenant = Mock()
        request.user.role = 'tenant_staff'

        response = custom_domain_detail_view(request, domain_id=1)

        assert response.status_code == status.HTTP_403_FORBIDDEN
        assert 'Only business owners' in response.data['error']



class TestCustomDomainVerifyView:
    """Tests for custom_domain_verify_view."""

    def test_returns_404_without_tenant(self):
        """Should return 404 when user has no tenant."""
        from smoothschedule.scheduling.schedule.api_views import custom_domain_verify_view

        factory = APIRequestFactory()
        request = factory.post('/api/custom-domains/1/verify/')
        request.user = Mock()
        request.user.tenant = None

        response = custom_domain_verify_view(request, domain_id=1)

        assert response.status_code == status.HTTP_404_NOT_FOUND
        assert 'No business' in response.data['error']

    def test_returns_403_when_not_owner(self):
        """Should return 403 when user is not owner."""
        from smoothschedule.scheduling.schedule.api_views import custom_domain_verify_view

        factory = APIRequestFactory()
        request = factory.post('/api/custom-domains/1/verify/')
        request.user = Mock()
        request.user.tenant = Mock()
        request.user.role = 'tenant_staff'

        response = custom_domain_verify_view(request, domain_id=1)

        assert response.status_code == status.HTTP_403_FORBIDDEN
        assert 'Only business owners' in response.data['error']



class TestCustomDomainSetPrimaryView:
    """Tests for custom_domain_set_primary_view."""

    def test_returns_404_without_tenant(self):
        """Should return 404 when user has no tenant."""
        from smoothschedule.scheduling.schedule.api_views import custom_domain_set_primary_view

        factory = APIRequestFactory()
        request = factory.post('/api/custom-domains/1/set-primary/')
        request.user = Mock()
        request.user.tenant = None

        response = custom_domain_set_primary_view(request, domain_id=1)

        assert response.status_code == status.HTTP_404_NOT_FOUND
        assert 'No business' in response.data['error']

    def test_returns_403_when_not_owner(self):
        """Should return 403 when user is not owner."""
        from smoothschedule.scheduling.schedule.api_views import custom_domain_set_primary_view

        factory = APIRequestFactory()
        request = factory.post('/api/custom-domains/1/set-primary/')
        request.user = Mock()
        request.user.tenant = Mock()
        request.user.role = 'tenant_staff'

        response = custom_domain_set_primary_view(request, domain_id=1)

        assert response.status_code == status.HTTP_403_FORBIDDEN
        assert 'Only business owners' in response.data['error']



class TestOAuthCredentialsView:
    """Tests for oauth_credentials_view."""

    def test_get_returns_404_without_tenant(self):
        """Should return 404 when user has no tenant."""
        from smoothschedule.scheduling.schedule.api_views import oauth_credentials_view

        factory = APIRequestFactory()
        request = factory.get('/api/oauth/credentials/')
        request.user = Mock()
        request.user.tenant = None

        response = oauth_credentials_view(request)

        assert response.status_code == status.HTTP_404_NOT_FOUND
        assert 'No business' in response.data['error']

    def test_get_returns_403_when_not_owner(self):
        """Should return 403 when user is not owner."""
        from smoothschedule.scheduling.schedule.api_views import oauth_credentials_view

        factory = APIRequestFactory()
        request = factory.get('/api/oauth/credentials/')

        mock_tenant = Mock()
        mock_tenant.can_manage_oauth_credentials = True

        request.user = Mock()
        request.user.tenant = mock_tenant
        request.user.role = 'tenant_staff'  # lowercase to match view check

        response = oauth_credentials_view(request)

        assert response.status_code == status.HTTP_403_FORBIDDEN
        assert 'Only business owners' in response.data['error']

    def test_get_returns_credentials(self):
        """Should return masked credentials for owner."""
        from smoothschedule.scheduling.schedule.api_views import oauth_credentials_view

        factory = APIRequestFactory()
        request = factory.get('/api/oauth/credentials/')

        mock_tenant = Mock()
        mock_tenant.oauth_credentials = {
            'google': {'client_id': 'goog-123', 'client_secret': 'secret-abc'}
        }
        mock_tenant.oauth_use_custom_credentials = True

        request.user = Mock()
        request.user.tenant = mock_tenant
        request.user.role = 'tenant_owner'

        response = oauth_credentials_view(request)

        assert response.status_code == status.HTTP_200_OK
        assert 'credentials' in response.data
        # Secret should be masked
        assert response.data['credentials']['google']['client_id'] == 'goog-123'
        assert '****' in response.data['credentials']['google']['client_secret']
