# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements.  See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership.  The ASF licenses this file
# to you 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 json
from unittest.mock import Mock

import click
import pytest
import responses as rsps

from archery.bot import CommentBot, CommandError, group


@pytest.fixture
def responses():
    with rsps.RequestsMock() as mock:
        yield mock


def github_url(path):
    return 'https://api.github.com:443/{}'.format(path.strip('/'))


@group()
def custom_handler():
    pass


@custom_handler.command()
@click.pass_obj
def extra(obj):
    return obj


@custom_handler.command()
@click.option('--force', '-f', is_flag=True)
def build(force):
    return force


@custom_handler.command()
@click.option('--name', required=True)
def benchmark(name):
    return name


def test_click_based_commands():
    assert custom_handler('build') is False
    assert custom_handler('build -f') is True

    assert custom_handler('benchmark --name strings') == 'strings'
    with pytest.raises(CommandError):
        assert custom_handler('benchmark')

    assert custom_handler('extra', extra='data') == {'extra': 'data'}


@pytest.mark.parametrize('fixture_name', [
    # the bot is not mentioned, nothing to do
    'event-issue-comment-not-mentioning-ursabot.json',
    # don't respond to itself, it prevents recursive comment storms!
    'event-issue-comment-by-ursabot.json',
    # non-authorized user sent the comment, do not respond
    'event-issue-comment-by-non-authorized-user.json',
])
def test_noop_events(load_fixture, fixture_name):
    payload = load_fixture(fixture_name)

    handler = Mock()
    bot = CommentBot(name='ursabot', token='', handler=handler)
    bot.handle('issue_comment', payload)

    handler.assert_not_called()


def test_issue_comment_without_pull_request(load_fixture, responses):
    responses.add(
        responses.GET,
        github_url('/repositories/169101701/issues/19'),
        json=load_fixture('issue-19.json'),
        status=200
    )
    responses.add(
        responses.GET,
        github_url('repos/ursa-labs/ursabot/pulls/19'),
        json={},
        status=404
    )
    responses.add(
        responses.POST,
        github_url('/repos/ursa-labs/ursabot/issues/19/comments'),
        json={}
    )

    def handler(command, **kwargs):
        pass

    payload = load_fixture('event-issue-comment-without-pull-request.json')
    bot = CommentBot(name='ursabot', token='', handler=handler)
    bot.handle('issue_comment', payload)

    post = responses.calls[2]
    assert json.loads(post.request.body) == {
        'body': "The comment bot only listens to pull request comments!"
    }


def test_respond_with_usage(load_fixture, responses):
    responses.add(
        responses.GET,
        github_url('/repositories/169101701/issues/26'),
        json=load_fixture('issue-26.json'),
        status=200
    )
    responses.add(
        responses.GET,
        github_url('/repos/ursa-labs/ursabot/pulls/26'),
        json=load_fixture('pull-request-26.json'),
        status=200
    )
    responses.add(
        responses.GET,
        github_url('/repos/ursa-labs/ursabot/issues/comments/480243811'),
        json=load_fixture('issue-comment-480243811.json')
    )
    responses.add(
        responses.POST,
        github_url('/repos/ursa-labs/ursabot/issues/26/comments'),
        json={}
    )

    def handler(command, **kwargs):
        raise CommandError('test-usage')

    payload = load_fixture('event-issue-comment-with-empty-command.json')
    bot = CommentBot(name='ursabot', token='', handler=handler)
    bot.handle('issue_comment', payload)

    post = responses.calls[3]
    assert json.loads(post.request.body) == {'body': '```\ntest-usage\n```'}


@pytest.mark.parametrize(('command', 'reaction'), [
    ('@ursabot build', '+1'),
    ('@ursabot listen', '-1'),
])
def test_issue_comment_with_commands(load_fixture, responses, command,
                                     reaction):
    responses.add(
        responses.GET,
        github_url('/repositories/169101701/issues/26'),
        json=load_fixture('issue-26.json'),
        status=200
    )
    responses.add(
        responses.GET,
        github_url('/repos/ursa-labs/ursabot/pulls/26'),
        json=load_fixture('pull-request-26.json'),
        status=200
    )
    responses.add(
        responses.GET,
        github_url('/repos/ursa-labs/ursabot/issues/comments/480248726'),
        json=load_fixture('issue-comment-480248726.json')
    )
    responses.add(
        responses.POST,
        github_url(
            '/repos/ursa-labs/ursabot/issues/comments/480248726/reactions'
        ),
        json={}
    )

    def handler(command, **kwargs):
        if command == 'build':
            return True
        else:
            raise ValueError('Only `build` command is supported.')

    payload = load_fixture('event-issue-comment-build-command.json')
    payload["comment"]["body"] = command

    bot = CommentBot(name='ursabot', token='', handler=handler)
    bot.handle('issue_comment', payload)

    post = responses.calls[3]
    assert json.loads(post.request.body) == {'content': reaction}
