#!/usr/bin/env python
# -*- coding: utf-8 -*-

from CTFd.models import Teams, Users
from CTFd.utils import set_config
from tests.helpers import (
    create_ctfd,
    destroy_ctfd,
    login_as_user,
    login_with_mlc,
    register_user,
)


def test_oauth_not_configured():
    """Test that OAuth redirection fails if OAuth settings aren't configured"""
    app = create_ctfd()
    with app.app_context():
        with app.test_client() as client:
            r = client.get("/oauth", follow_redirects=False)
            assert r.location == "/login"
            r = client.get(r.location)
            resp = r.get_data(as_text=True)
            assert "OAuth Settings not configured" in resp
    destroy_ctfd(app)


def test_oauth_configured_flow():
    """Test that MLC integration works properly but does not allow registration (account creation) if disabled"""
    app = create_ctfd(user_mode="teams")
    app.config.update(
        {
            "OAUTH_CLIENT_ID": "ctfd_testing_client_id",
            "OAUTH_CLIENT_SECRET": "ctfd_testing_client_secret",
            "OAUTH_AUTHORIZATION_ENDPOINT": "http://auth.localhost/oauth/authorize",
            "OAUTH_TOKEN_ENDPOINT": "http://auth.localhost/oauth/token",
            "OAUTH_API_ENDPOINT": "http://api.localhost/user",
        }
    )
    with app.app_context():
        set_config("registration_visibility", "private")
        assert Users.query.count() == 1
        assert Teams.query.count() == 0

        client = login_with_mlc(app, raise_for_error=False)

        assert Users.query.count() == 1

        # Users shouldn't be able to register because registration is disabled
        resp = client.get("http://localhost/login").get_data(as_text=True)
        assert "Public registration is disabled" in resp

        set_config("registration_visibility", "public")
        client = login_with_mlc(app)

        # Users should be able to register now
        assert Users.query.count() == 2
        user = Users.query.filter_by(email="user@examplectf.com").first()
        assert user.oauth_id == 1337
        assert user.team_id == 1

        # Teams should be created
        assert Teams.query.count() == 1
        team = Teams.query.filter_by(id=1).first()
        assert team.oauth_id == 1234

        client.get("/logout")

        # Users should still be able to login if registration is disabled
        set_config("registration_visibility", "private")
        client = login_with_mlc(app)
        with client.session_transaction() as sess:
            assert sess["id"]
            assert sess["nonce"]
            assert sess["hash"]
    destroy_ctfd(app)


def test_oauth_login_upgrade():
    """Test that users who use MLC after having registered will be associated with their MLC account"""
    app = create_ctfd(user_mode="teams")
    app.config.update(
        {
            "OAUTH_CLIENT_ID": "ctfd_testing_client_id",
            "OAUTH_CLIENT_SECRET": "ctfd_testing_client_secret",
            "OAUTH_AUTHORIZATION_ENDPOINT": "http://auth.localhost/oauth/authorize",
            "OAUTH_TOKEN_ENDPOINT": "http://auth.localhost/oauth/token",
            "OAUTH_API_ENDPOINT": "http://api.localhost/user",
        }
    )
    with app.app_context():
        register_user(app)
        assert Users.query.count() == 2
        set_config("registration_visibility", "private")

        # Users should still be able to login
        client = login_as_user(app)
        client.get("/logout")

        user = Users.query.filter_by(id=2).first()
        assert user.oauth_id is None
        assert user.team_id is None

        login_with_mlc(app)

        assert Users.query.count() == 2

        # Logging in with MLC should insert an OAuth ID and team ID
        user = Users.query.filter_by(id=2).first()
        assert user.oauth_id
        assert user.verified
        assert user.team_id
    destroy_ctfd(app)
