# Copyright 2024 Google Inc.
#
# 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.

"""Tests for the fetchchannels module, verifying the fetching of Chrome release info."""

import json
from unittest import mock

import flask

import testing_config  # Must be imported first
from internals import fetchchannels


class ChannelsAPITest(testing_config.CustomTestCase):
    """Tests for the channels API."""

    @mock.patch('requests.get')
    def test_fetch_chrome_release_info__found(self, mock_requests_get):
        """We can get channel data from the chromiumdash app."""
        mock_requests_get.return_value = testing_config.Blank(
            status_code=200,
            content=json.dumps(
                {
                    'mstones': [
                        {
                            'owners': 'ignored',
                            'feature_freeze': 'ignored',
                            'ldaps': 'ignored',
                            'everything else': 'kept',
                        }
                    ],
                }
            ),
        )

        actual = fetchchannels.fetch_chrome_release_info(90)

        self.assertEqual({'everything else': 'kept'}, actual)

    @mock.patch('requests.get')
    def test_fetch_chrome_release_info__not_found(self, mock_requests_get):
        """If chromiumdash app does not have the data, use a placeholder."""
        mock_requests_get.return_value = testing_config.Blank(
            status_code=404, content=''
        )

        actual = fetchchannels.fetch_chrome_release_info(91)

        self.assertEqual(
            {
                'stable_date': None,
                'earliest_beta': None,
                'latest_beta': None,
                'mstone': 91,
                'version': 91,
            },
            actual,
        )

    @mock.patch('requests.get')
    def test_fetch_chrome_release_info__error(self, mock_requests_get):
        """We can get channel data from the chromiumdash app."""
        mock_requests_get.return_value = testing_config.Blank(
            status_code=200, content='{'
        )

        actual = fetchchannels.fetch_chrome_release_info(90)

        self.assertEqual(
            {
                'stable_date': None,
                'earliest_beta': None,
                'latest_beta': None,
                'mstone': 90,
                'version': 90,
            },
            actual,
        )

    @mock.patch('internals.fetchchannels.get_omaha_data')
    def test_get_current_channel_milestone(self, mock_get_omaha):
        """It sets flask.g attributes on first call and reads from flask.g on cache hits."""
        mock_get_omaha.return_value = [
            {
                'versions': [
                    {'channel': 'stable', 'version': '147.0.7727.56'},
                    {'channel': 'beta', 'version': '148.0.7778.5'},
                    {'channel': 'dev', 'version': '149.0.7779.3'},
                ]
            }
        ]

        app = flask.Flask(__name__)
        with app.test_request_context('/'):
            # First calls compute milestones for stable, beta, dev and set flask.g attributes
            self.assertEqual(147, fetchchannels.get_current_stable_milestone())
            self.assertEqual(148, fetchchannels.get_current_beta_milestone())
            self.assertEqual(
                149,
                fetchchannels.get_current_channel_milestone(
                    fetchchannels.Channel.DEV
                ),
            )

            # Verify get_omaha_data was called exactly 3 times (once per channel)
            self.assertEqual(3, mock_get_omaha.call_count)

            # Verify attributes are set on flask.g with exact key names
            self.assertEqual(147, getattr(flask.g, 'current_stable_milestone'))
            self.assertEqual(148, getattr(flask.g, 'current_beta_milestone'))
            self.assertEqual(149, getattr(flask.g, 'current_dev_milestone'))

            # Reset mock call counter
            mock_get_omaha.reset_mock()

            # Subsequent calls read directly from flask.g without querying get_omaha_data()
            self.assertEqual(147, fetchchannels.get_current_stable_milestone())
            self.assertEqual(148, fetchchannels.get_current_beta_milestone())
            self.assertEqual(
                149,
                fetchchannels.get_current_channel_milestone(
                    fetchchannels.Channel.DEV
                ),
            )
            mock_get_omaha.assert_not_called()
