# Copyright 2017 Google LLC All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import unittest

import mock

_FLASK_TRACE_ID = "flask0id"
_FLASK_SPAN_ID = "span0flask"
_FLASK_HTTP_REQUEST = {"requestUrl": "https://flask.palletsprojects.com/en/1.1.x/"}
_DJANGO_TRACE_ID = "django0id"
_DJANGO_SPAN_ID = "span0django"
_DJANGO_HTTP_REQUEST = {"requestUrl": "https://www.djangoproject.com/"}


class Test_get_request_data_from_flask(unittest.TestCase):
    @staticmethod
    def _call_fut():
        from google.cloud.logging_v2.handlers import _helpers

        http, trace, span, sampled = _helpers.get_request_data_from_flask()
        return http, trace, span, sampled

    @staticmethod
    def create_app():
        import flask

        app = flask.Flask(__name__)

        @app.route("/")
        def index():
            return "test flask trace"  # pragma: NO COVER

        return app

    def test_no_context_header(self):
        app = self.create_app()
        with app.test_request_context(path="/", headers={}):
            http_request, trace_id, span_id, sampled = self._call_fut()

        self.assertIsNone(trace_id)
        self.assertIsNone(span_id)
        self.assertEqual(sampled, False)
        self.assertEqual(http_request["requestMethod"], "GET")

    def test_xcloud_header(self):
        flask_trace_header = "X_CLOUD_TRACE_CONTEXT"
        expected_trace_id = _FLASK_TRACE_ID
        expected_span_id = _FLASK_SPAN_ID
        flask_trace_id = f"{expected_trace_id}/{expected_span_id};o=1"

        app = self.create_app()
        context = app.test_request_context(
            path="/", headers={flask_trace_header: flask_trace_id}
        )

        with context:
            http_request, trace_id, span_id, sampled = self._call_fut()

        self.assertEqual(trace_id, expected_trace_id)
        self.assertEqual(span_id, expected_span_id)
        self.assertEqual(sampled, True)
        self.assertEqual(http_request["requestMethod"], "GET")

    def test_traceparent_header(self):
        flask_trace_header = "TRACEPARENT"
        expected_trace_id = "4bf92f3577b34da6a3ce929d0e0e4736"
        expected_span_id = "00f067aa0ba902b7"
        flask_trace_id = f"00-{expected_trace_id}-{expected_span_id}-01"

        app = self.create_app()
        context = app.test_request_context(
            path="/", headers={flask_trace_header: flask_trace_id}
        )

        with context:
            http_request, trace_id, span_id, sampled = self._call_fut()

        self.assertEqual(trace_id, expected_trace_id)
        self.assertEqual(span_id, expected_span_id)
        self.assertEqual(sampled, True)
        self.assertEqual(http_request["requestMethod"], "GET")

    def test_http_request_populated(self):
        expected_path = "http://testserver/123"
        expected_agent = "Mozilla/5.0"
        expected_referrer = "self"
        expected_ip = "10.1.2.3"
        headers = {
            "User-Agent": expected_agent,
            "Referer": expected_referrer,
        }

        app = self.create_app()
        with app.test_request_context(
            expected_path, headers=headers, environ_base={"REMOTE_ADDR": expected_ip}
        ):
            http_request, *_ = self._call_fut()