"""Settings-driven search integrations (ServiceNow + employee-ID pattern).

The ServiceNow ticket prefixes, the ServiceNow search URL/enabled flag, and the
employee-ID recognition pattern all ship as GE defaults but are configurable
per-site via Settings. These tests pin that the search endpoint honors those
settings and that a bad employeeid_pattern regex falls back rather than 500ing.

Settings are cached, so every case seeds its rows and calls
invalidate_settings_cache() before exercising search.
"""

from shopdb.core.models import Setting
from shopdb.core.api.settings import invalidate_settings_cache
from shopdb.core.api.search import _get_search_integrations, _classify_query


def _redirect(client, auth_headers, term):
    resp = client.get(f'/api/search?q={term}', headers=auth_headers)
    assert resp.status_code == 200, resp.get_json()
    return resp.get_json()['data'].get('redirect')


def test_default_prefix_classifies_servicenow(client, db, auth_headers):
    """With no override, a GE-prefixed ticket redirects to ServiceNow."""
    invalidate_settings_cache()
    redirect = _redirect(client, auth_headers, 'GEINC123')
    assert redirect is not None
    assert redirect['type'] == 'servicenow'


def test_custom_prefix_classifies_servicenow(client, db, auth_headers):
    """A site-configured prefix classifies its tickets as ServiceNow."""
    Setting.set('servicenow_ticket_prefixes', 'ACMEINC', valuetype='string',
                category='integrations')
    invalidate_settings_cache()
    redirect = _redirect(client, auth_headers, 'ACMEINC123')
    assert redirect is not None
    assert redirect['type'] == 'servicenow'
    # Ticket is url-encoded into the {ticket} placeholder.
    assert 'ACMEINC123' in redirect['url']


def test_custom_prefix_ignores_default_prefix(client, db, auth_headers):
    """Overriding the prefixes drops the built-in GE prefixes."""
    Setting.set('servicenow_ticket_prefixes', 'ACMEINC', valuetype='string',
                category='integrations')
    invalidate_settings_cache()
    redirect = _redirect(client, auth_headers, 'GEINC123')
    # GEINC is no longer a configured prefix, so no ServiceNow redirect.
    assert redirect is None or redirect.get('type') != 'servicenow'


def test_disabled_servicenow_yields_no_redirect(client, db, auth_headers):
    """servicenow_enabled=false suppresses the ServiceNow redirect entirely."""
    Setting.set('servicenow_enabled', False, valuetype='boolean',
                category='integrations')
    invalidate_settings_cache()
    redirect = _redirect(client, auth_headers, 'GEINC123')
    assert redirect is None or redirect.get('type') != 'servicenow'


def test_blank_search_url_yields_no_redirect(client, db, auth_headers):
    """An empty servicenow_search_url disables the redirect."""
    Setting.set('servicenow_search_url', '', valuetype='string',
                category='integrations')
    invalidate_settings_cache()
    redirect = _redirect(client, auth_headers, 'GEINC123')
    assert redirect is None or redirect.get('type') != 'servicenow'


def test_custom_employeeid_pattern_recognizes_six_digits(client, db, auth_headers):
    """A ^\\d{6}$ pattern makes six-digit IDs classify as employee queries."""
    Setting.set('employeeid_pattern', r'^\d{6}$', valuetype='string',
                category='site')
    invalidate_settings_cache()
    integrations = _get_search_integrations()
    assert _classify_query('123456', integrations)['is_sso'] is True
    # Anchored pattern rejects the old nine-digit shape.
    assert _classify_query('123456789', integrations)['is_sso'] is False


def test_default_employeeid_pattern_recognizes_nine_digits(client, db, auth_headers):
    """The shipped default recognizes nine-digit SSO IDs."""
    invalidate_settings_cache()
    integrations = _get_search_integrations()
    assert _classify_query('123456789', integrations)['is_sso'] is True
    assert _classify_query('123456', integrations)['is_sso'] is False


def test_invalid_employeeid_pattern_falls_back(client, db, auth_headers):
    """A malformed regex falls back to nine-digit matching without erroring."""
    Setting.set('employeeid_pattern', '[', valuetype='string', category='site')
    invalidate_settings_cache()
    # Must not raise on compile of the bad pattern.
    integrations = _get_search_integrations()
    assert _classify_query('123456789', integrations)['is_sso'] is True
    assert _classify_query('12345', integrations)['is_sso'] is False


def test_invalid_pattern_search_does_not_500(client, db, auth_headers):
    """End-to-end: a bad employeeid_pattern must not break the search endpoint."""
    Setting.set('employeeid_pattern', '(', valuetype='string', category='site')
    invalidate_settings_cache()
    resp = client.get('/api/search?q=hello', headers=auth_headers)
    assert resp.status_code == 200, resp.get_json()
