"""Support teams + contacts: team/contact CRUD, lookup, delete-guard, import.

The application/support-team wiring: a team owns ordered contacts, an
application carries one team, and its payload flattens the team name/url +
active contacts so the frontend needs a single call.
"""

IMPORT_HEADER = {'X-Import-Mode': 'true'}
LEGACY_CREATED = '2020-01-05 08:30:00'
LEGACY_MODIFIED = '2021-06-07T14:15:16'


def _import_headers(auth_headers):
    merged = dict(auth_headers)
    merged.update(IMPORT_HEADER)
    return merged


def _create_team(client, auth_headers, teamname='Controls', teamurl=None):
    return client.post('/api/supportteams',
                       json={'teamname': teamname, 'teamurl': teamurl},
                       headers=auth_headers)


# ---------------------------------------------------------------------------
# Team CRUD
# ---------------------------------------------------------------------------

def test_create_and_get_team(client, db, auth_headers):
    """Create a team, then fetch it back with an (empty) contacts list."""
    resp = _create_team(client, auth_headers, 'Controls',
                        'https://servicenow.example/group/controls')
    assert resp.status_code == 201, resp.get_json()
    teamid = resp.get_json()['data']['supportteamid']

    got = client.get(f'/api/supportteams/{teamid}', headers=auth_headers)
    assert got.status_code == 200
    data = got.get_json()['data']
    assert data['teamname'] == 'Controls'
    assert data['teamurl'] == 'https://servicenow.example/group/controls'
    assert data['contacts'] == []


def test_create_team_requires_teamname(client, db, auth_headers):
    resp = client.post('/api/supportteams', json={}, headers=auth_headers)
    assert resp.status_code == 400


def test_create_team_duplicate_conflict(client, db, auth_headers):
    _create_team(client, auth_headers, 'Controls')
    dup = _create_team(client, auth_headers, 'Controls')
    assert dup.status_code == 409


def test_update_team(client, db, auth_headers):
    teamid = _create_team(client, auth_headers, 'Controls').get_json()['data']['supportteamid']
    resp = client.put(f'/api/supportteams/{teamid}',
                      json={'teamname': 'Controls Renamed',
                            'teamurl': 'https://x.example'},
                      headers=auth_headers)
    assert resp.status_code == 200
    assert resp.get_json()['data']['teamname'] == 'Controls Renamed'


def test_delete_team(client, db, auth_headers):
    teamid = _create_team(client, auth_headers, 'ToDelete').get_json()['data']['supportteamid']
    resp = client.delete(f'/api/supportteams/{teamid}', headers=auth_headers)
    assert resp.status_code == 200
    gone = client.get(f'/api/supportteams/{teamid}', headers=auth_headers)
    assert gone.status_code == 404


# ---------------------------------------------------------------------------
# teamname exact-match lookup (import recipe) + active filter
# ---------------------------------------------------------------------------

def test_teamname_lookup_filter(client, db, auth_headers):
    for name in ('Controls', 'ControlsB', 'Networking'):
        _create_team(client, auth_headers, name)
    listed = client.get('/api/supportteams?teamname=Controls', headers=auth_headers)
    assert listed.status_code == 200
    rows = listed.get_json()['data']
    assert len(rows) == 1
    assert rows[0]['teamname'] == 'Controls'


def test_list_active_filter_hides_inactive(client, db, auth_headers):
    teamid = _create_team(client, auth_headers, 'Retired').get_json()['data']['supportteamid']
    client.put(f'/api/supportteams/{teamid}', json={'isactive': False},
               headers=auth_headers)
    active = client.get('/api/supportteams', headers=auth_headers)
    assert all(t['teamname'] != 'Retired' for t in active.get_json()['data'])
    allteams = client.get('/api/supportteams?active=false', headers=auth_headers)
    assert any(t['teamname'] == 'Retired' for t in allteams.get_json()['data'])


# ---------------------------------------------------------------------------
# Delete-with-applications 409
# ---------------------------------------------------------------------------

def test_delete_team_with_applications_conflicts(client, db, auth_headers):
    teamid = _create_team(client, auth_headers, 'InUse').get_json()['data']['supportteamid']
    appresp = client.post('/api/applications',
                          json={'appname': 'DependentApp',
                                'supportteamid': teamid},
                          headers=auth_headers)
    assert appresp.status_code == 201, appresp.get_json()

    conflict = client.delete(f'/api/supportteams/{teamid}', headers=auth_headers)
    assert conflict.status_code == 409
    # Still there.
    assert client.get(f'/api/supportteams/{teamid}',
                      headers=auth_headers).status_code == 200


# ---------------------------------------------------------------------------
# Nested contact CRUD + ordering
# ---------------------------------------------------------------------------

def test_contact_crud_and_ordering(client, db, auth_headers):
    teamid = _create_team(client, auth_headers, 'Controls').get_json()['data']['supportteamid']

    # Add two contacts out of sort order.
    c2 = client.post(f'/api/supportteams/{teamid}/contacts',
                     json={'name': 'Second', 'sso': '222', 'sortorder': 2},
                     headers=auth_headers)
    assert c2.status_code == 201, c2.get_json()
    c1 = client.post(f'/api/supportteams/{teamid}/contacts',
                     json={'name': 'First', 'sso': '111', 'sortorder': 1},
                     headers=auth_headers)
    assert c1.status_code == 201

    # Team now nests active contacts in sortorder.
    team = client.get(f'/api/supportteams/{teamid}', headers=auth_headers).get_json()['data']
    names = [c['name'] for c in team['contacts']]
    assert names == ['First', 'Second']

    # Update one contact.
    contactid = c1.get_json()['data']['contactid']
    upd = client.put(f'/api/supportteams/{teamid}/contacts/{contactid}',
                     json={'name': 'First Updated'}, headers=auth_headers)
    assert upd.status_code == 200
    assert upd.get_json()['data']['name'] == 'First Updated'

    # Delete the other contact.
    otherid = c2.get_json()['data']['contactid']
    dele = client.delete(f'/api/supportteams/{teamid}/contacts/{otherid}',
                         headers=auth_headers)
    assert dele.status_code == 200
    team = client.get(f'/api/supportteams/{teamid}', headers=auth_headers).get_json()['data']
    assert [c['name'] for c in team['contacts']] == ['First Updated']


def test_contact_requires_name(client, db, auth_headers):
    teamid = _create_team(client, auth_headers, 'Controls').get_json()['data']['supportteamid']
    resp = client.post(f'/api/supportteams/{teamid}/contacts', json={},
                       headers=auth_headers)
    assert resp.status_code == 400


def test_delete_team_cascades_contacts(client, db, auth_headers):
    from shopdb.core.models import SupportTeamContact
    teamid = _create_team(client, auth_headers, 'Controls').get_json()['data']['supportteamid']
    client.post(f'/api/supportteams/{teamid}/contacts',
                json={'name': 'Someone'}, headers=auth_headers)
    client.delete(f'/api/supportteams/{teamid}', headers=auth_headers)
    assert SupportTeamContact.query.filter_by(supportteamid=teamid).count() == 0


# ---------------------------------------------------------------------------
# Application carries the team + flattened contacts
# ---------------------------------------------------------------------------

def test_application_carries_supportteam_payload(client, db, auth_headers):
    teamid = _create_team(client, auth_headers, 'Controls',
                         'https://sn.example/controls').get_json()['data']['supportteamid']
    client.post(f'/api/supportteams/{teamid}/contacts',
                json={'name': 'Alice', 'sso': 'a01', 'sortorder': 0},
                headers=auth_headers)

    appresp = client.post('/api/applications',
                          json={'appname': 'TeamApp', 'supportteamid': teamid},
                          headers=auth_headers)
    appid = appresp.get_json()['data']['appid']

    got = client.get(f'/api/applications/{appid}', headers=auth_headers)
    data = got.get_json()['data']
    assert data['supportteamid'] == teamid
    assert data['supportteamname'] == 'Controls'
    assert data['teamurl'] == 'https://sn.example/controls'
    assert data['contacts'] == [{'name': 'Alice', 'sso': 'a01'}]


# ---------------------------------------------------------------------------
# Import-mode timestamps
# ---------------------------------------------------------------------------

def test_import_mode_preserves_team_timestamps(client, db, auth_headers):
    resp = client.post('/api/supportteams',
                       json={'teamname': 'Legacy',
                             'createddate': LEGACY_CREATED,
                             'modifieddate': LEGACY_MODIFIED},
                       headers=_import_headers(auth_headers))
    assert resp.status_code == 201, resp.get_json()

    from shopdb.core.models import SupportTeam
    team = SupportTeam.query.filter_by(teamname='Legacy').first()
    assert team.createddate.year == 2020 and team.createddate.month == 1
    assert team.modifieddate.year == 2021


def test_import_mode_preserves_contact_timestamps(client, db, auth_headers):
    teamid = _create_team(client, auth_headers, 'Controls').get_json()['data']['supportteamid']
    resp = client.post(f'/api/supportteams/{teamid}/contacts',
                       json={'name': 'LegacyOwner',
                             'createddate': LEGACY_CREATED,
                             'modifieddate': LEGACY_MODIFIED},
                       headers=_import_headers(auth_headers))
    assert resp.status_code == 201, resp.get_json()

    from shopdb.core.models import SupportTeamContact
    contact = SupportTeamContact.query.filter_by(name='LegacyOwner').first()
    assert contact.createddate.year == 2020
    assert contact.modifieddate.year == 2021


# ---------------------------------------------------------------------------
# Authz (belt-and-suspenders; the sweep in test_authz also covers these)
# ---------------------------------------------------------------------------

def test_member_cannot_create_team(client, db, member_headers):
    resp = client.post('/api/supportteams', json={'teamname': 'X'},
                       headers=member_headers)
    assert resp.status_code == 403
